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)
{