Author: ion
Date: Wed Aug 28 05:04:36 2013
New Revision: 59843
URL: http://svn.reactos.org/svn/reactos?rev=59843&view=rev
Log:
[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***
Modified:
trunk/reactos/dll/win32/advapi32/service/sctrl.c
Modified: trunk/reactos/dll/win32/advapi32/service/sctrl.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/service…
==============================================================================
--- trunk/reactos/dll/win32/advapi32/service/sctrl.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/advapi32/service/sctrl.c [iso-8859-1] Wed Aug 28 05:04:36 2013
@@ -288,7 +288,8 @@
{
LPWSTR *lpVector;
LPWSTR *lpArg;
- DWORD i;
+ DWORD i, cbServiceName, cbTotal;
+ LPWSTR pszServiceName;
if (ControlPacket == NULL || lpArgCount == NULL || lpArgVector == NULL)
return ERROR_INVALID_PARAMETER;
@@ -296,28 +297,47 @@
*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;
-
- memcpy(lpVector,
+ cbTotal = ControlPacket->dwSize - ControlPacket->dwArgumentsOffset +
+ cbServiceName + sizeof(LPWSTR);
+ }
+ else
+ {
+ cbTotal = cbServiceName + sizeof(LPWSTR);
+ }
+
+ 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;
}
@@ -342,6 +362,9 @@
*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)
{