[ADVAPI32/SERVICES]: Windows services (as per MSDN and testing) must always get at least one parameter -- the service name, in the argument vector. However, in ReactOS, unless optional custom parameters were sent (when starting a service), services got 0 parameters and a NULL argument vector. Since services on Windows know this is impossible, many dereference the vector without checking for NULL (including Windows Svchost.exe). Either way, it's bogus for us not ever sending the name as the first parameter. So I fixed ScBuildUnicodeArgsVector to always either pre-pend the service name (if the caller gave us some parameters already), or do use the name as the sole parameter (if the caller sent none). This now works as on Windows, and should greately help with 3rd party service compatibility.

***NOTE THAT I ONLY DID THIS FOR UNICODE. I DID NOT BOTHER TO FIX THE ANSI VERSION. ERIC KOHL, PLEASE REVIEW & FIX AS APPROPRIATE***

svn path=/trunk/; revision=59843
This commit is contained in:
Alex Ionescu 2013-08-28 05:04:36 +00:00
parent 05f3a7e599
commit d78172a8cd

View file

@ -288,7 +288,8 @@ ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket,
{
LPWSTR *lpVector;
LPWSTR *lpArg;
DWORD i;
DWORD i, cbServiceName, cbTotal;
LPWSTR pszServiceName;
if (ControlPacket == NULL || lpArgCount == NULL || lpArgVector == NULL)
return ERROR_INVALID_PARAMETER;
@ -296,29 +297,48 @@ ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket,
*lpArgCount = 0;
*lpArgVector = NULL;
pszServiceName = (PWSTR) ((PBYTE) ControlPacket + ControlPacket->dwServiceNameOffset);
cbServiceName = lstrlenW(pszServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
if (ControlPacket->dwArgumentsCount > 0)
{
lpVector = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
if (lpVector == NULL)
return ERROR_OUTOFMEMORY;
cbTotal = ControlPacket->dwSize - ControlPacket->dwArgumentsOffset +
cbServiceName + sizeof(LPWSTR);
}
else
{
cbTotal = cbServiceName + sizeof(LPWSTR);
}
memcpy(lpVector,
lpVector = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
cbTotal);
if (lpVector == NULL)
return ERROR_OUTOFMEMORY;
lpArg = lpVector;
*lpArg = (LPWSTR)(lpArg + 1);
lpArg++;
memcpy(lpArg, pszServiceName, cbServiceName);
lpArg = (LPWSTR*) ((ULONG_PTR) lpArg + cbServiceName);
if (ControlPacket->dwArgumentsCount > 0)
{
memcpy(lpArg,
((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
lpArg = lpVector;
for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
{
*lpArg = (LPWSTR)((ULONG_PTR)lpArg + (ULONG_PTR)*lpArg);
lpArg++;
}
*lpArgCount = ControlPacket->dwArgumentsCount;
*lpArgVector = lpVector;
}
*lpArgCount = ControlPacket->dwArgumentsCount + 1;
*lpArgVector = lpVector;
return ERROR_SUCCESS;
}
@ -343,6 +363,9 @@ ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket,
*lpArgCount = 0;
*lpArgVector = NULL;
/* FIXME: There should always be one argument (the name) sent to services... */
/* FIXME: See the Unicode version above on how to achieve this */
if (ControlPacket->dwArgumentsCount > 0)
{
dwVectorSize = ControlPacket->dwArgumentsCount * sizeof(LPWSTR);