[SERVICES/ADVAPI32]

Pass the service start argument vector to the started service main function. ANSI services are not supported yet.

svn path=/trunk/; revision=53564
This commit is contained in:
Eric Kohl 2011-09-03 19:47:56 +00:00
parent 1a358ac727
commit ff2da6c81c
2 changed files with 177 additions and 152 deletions

View file

@ -1002,6 +1002,8 @@ ScmSendStartCommand(PSERVICE Service,
DWORD dwReadCount = 0;
DWORD dwError = ERROR_SUCCESS;
DWORD i;
PWSTR *pOffPtr;
PWSTR pArgPtr;
DPRINT("ScmSendStartCommand() called\n");
@ -1043,16 +1045,25 @@ ScmSendStartCommand(PSERVICE Service,
/* Copy argument list */
if (argc > 0 && argv != NULL)
{
// Ptr += wcslen(Service->lpServiceName) + 1;
// Ptr = ALIGN_UP_POINTER(Ptr, LPWSTR);
Ptr += wcslen(Service->lpServiceName) + 1;
pOffPtr = (PWSTR*)ALIGN_UP_POINTER(Ptr, PWSTR);
pArgPtr = (PWSTR)((ULONG_PTR)pOffPtr + argc * sizeof(PWSTR));
// ControlPacket->dwArgumentsOffset = (DWORD)((INT_PTR)Ptr - (INT_PTR)ControlPacket);
ControlPacket->dwArgumentsCount = argc;
ControlPacket->dwArgumentsOffset = (DWORD)((ULONG_PTR)pOffPtr - (ULONG_PTR)ControlPacket);
DPRINT("dwArgumentsCount: %lu\n", ControlPacket->dwArgumentsCount);
DPRINT("dwArgumentsOffset: %lu\n", ControlPacket->dwArgumentsOffset);
#if 0
memcpy(Ptr, Arguments, ArgsLength);
Ptr += ArgsLength;
#endif
for (i = 0; i < argc; i++)
{
wcscpy(pArgPtr, argv[i]);
*pOffPtr = (PWSTR)((ULONG_PTR)pArgPtr - (ULONG_PTR)pOffPtr);
DPRINT("offset: %p\n", *pOffPtr);
pArgPtr += wcslen(argv[i]) + 1;
pOffPtr++;
}
}
/* Send the start command */

View file

@ -18,20 +18,35 @@ WINE_DEFAULT_DEBUG_CHANNEL(advapi);
/* TYPES *********************************************************************/
typedef struct _SERVICE_THREAD_PARAMSA
{
LPSERVICE_MAIN_FUNCTIONA lpServiceMain;
DWORD dwArgCount;
LPSTR *lpArgVector;
} SERVICE_THREAD_PARAMSA, *PSERVICE_THREAD_PARAMSA;
typedef struct _SERVICE_THREAD_PARAMSW
{
LPSERVICE_MAIN_FUNCTIONW lpServiceMain;
DWORD dwArgCount;
LPWSTR *lpArgVector;
} SERVICE_THREAD_PARAMSW, *PSERVICE_THREAD_PARAMSW;
typedef struct _ACTIVE_SERVICE
{
SERVICE_STATUS_HANDLE hServiceStatus;
UNICODE_STRING ServiceName;
union
{
LPSERVICE_MAIN_FUNCTIONA lpFuncA;
LPSERVICE_MAIN_FUNCTIONW lpFuncW;
} Main;
SERVICE_THREAD_PARAMSA A;
SERVICE_THREAD_PARAMSW W;
} ThreadParams;
LPHANDLER_FUNCTION HandlerFunction;
LPHANDLER_FUNCTION_EX HandlerFunctionEx;
LPVOID HandlerContext;
BOOL bUnicode;
LPWSTR Arguments;
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
@ -148,122 +163,40 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
static DWORD WINAPI
ScServiceMainStub(LPVOID Context)
{
PACTIVE_SERVICE lpService;
DWORD dwArgCount = 0;
DWORD dwLength = 0;
DWORD dwLen;
LPWSTR lpPtr;
lpService = (PACTIVE_SERVICE)Context;
PACTIVE_SERVICE lpService = (PACTIVE_SERVICE)Context;
TRACE("ScServiceMainStub() called\n");
/* Count arguments */
lpPtr = lpService->Arguments;
while (*lpPtr)
{
TRACE("arg: %S\n", lpPtr);
dwLen = wcslen(lpPtr) + 1;
dwArgCount++;
dwLength += dwLen;
lpPtr += dwLen;
}
TRACE("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);
/* Build the argument vector and call the main service routine */
/* Call the main service routine and free the arguments vector */
if (lpService->bUnicode)
{
LPWSTR *lpArgVector;
LPWSTR Ptr;
(lpService->ThreadParams.W.lpServiceMain)(lpService->ThreadParams.W.dwArgCount,
lpService->ThreadParams.W.lpArgVector);
lpArgVector = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
(dwArgCount + 1) * sizeof(LPWSTR));
if (lpArgVector == NULL)
return ERROR_OUTOFMEMORY;
dwArgCount = 0;
Ptr = lpService->Arguments;
while (*Ptr)
if (lpService->ThreadParams.A.lpArgVector != NULL)
{
lpArgVector[dwArgCount] = Ptr;
HeapFree(GetProcessHeap(),
0,
lpService->ThreadParams.W.lpArgVector);
dwArgCount++;
Ptr += (wcslen(Ptr) + 1);
lpService->ThreadParams.W.lpArgVector = NULL;
lpService->ThreadParams.W.dwArgCount = 0;
}
lpArgVector[dwArgCount] = NULL;
(lpService->Main.lpFuncW)(dwArgCount, lpArgVector);
HeapFree(GetProcessHeap(),
0,
lpArgVector);
}
else
{
LPSTR *lpArgVector;
LPSTR Ptr;
LPSTR AnsiString;
DWORD AnsiLength;
(lpService->ThreadParams.A.lpServiceMain)(lpService->ThreadParams.A.dwArgCount,
lpService->ThreadParams.A.lpArgVector);
AnsiLength = WideCharToMultiByte(CP_ACP,
0,
lpService->Arguments,
dwLength,
NULL,
0,
NULL,
NULL);
if (AnsiLength == 0)
return ERROR_INVALID_PARAMETER; /* ? */
AnsiString = HeapAlloc(GetProcessHeap(),
0,
AnsiLength + 1);
if (AnsiString == NULL)
return ERROR_OUTOFMEMORY;
WideCharToMultiByte(CP_ACP,
0,
lpService->Arguments,
dwLength,
AnsiString,
AnsiLength,
NULL,
NULL);
AnsiString[AnsiLength] = ANSI_NULL;
lpArgVector = HeapAlloc(GetProcessHeap(),
0,
(dwArgCount + 1) * sizeof(LPSTR));
if (lpArgVector == NULL)
if (lpService->ThreadParams.A.lpArgVector != NULL)
{
HeapFree(GetProcessHeap(),
0,
AnsiString);
return ERROR_OUTOFMEMORY;
0,
lpService->ThreadParams.A.lpArgVector);
lpService->ThreadParams.A.lpArgVector = NULL;
lpService->ThreadParams.A.dwArgCount = 0;
}
dwArgCount = 0;
Ptr = AnsiString;
while (*Ptr)
{
lpArgVector[dwArgCount] = Ptr;
dwArgCount++;
Ptr += (strlen(Ptr) + 1);
}
lpArgVector[dwArgCount] = NULL;
(lpService->Main.lpFuncA)(dwArgCount, lpArgVector);
HeapFree(GetProcessHeap(),
0,
lpArgVector);
HeapFree(GetProcessHeap(),
0,
AnsiString);
}
return ERROR_SUCCESS;
@ -350,9 +283,8 @@ ScStartService(PACTIVE_SERVICE lpService,
{
HANDLE ThreadHandle;
DWORD ThreadId;
PWSTR pServiceName;
PWSTR Ptr;
DWORD dwArgumentsSize;
LPWSTR *lpArgW;
DWORD i;
TRACE("ScStartService() called\n");
TRACE("Size: %lu\n", ControlPacket->dwSize);
@ -361,43 +293,106 @@ ScStartService(PACTIVE_SERVICE lpService,
/* Set the service status handle */
lpService->hServiceStatus = ControlPacket->hServiceStatus;
pServiceName = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
if (lpService->bUnicode == TRUE)
{
lpService->ThreadParams.W.dwArgCount = ControlPacket->dwArgumentsCount;
lpService->ThreadParams.W.lpArgVector = NULL;
/* Get the service name size */
dwArgumentsSize = (wcslen(pServiceName) + 1) * sizeof(WCHAR);
if (ControlPacket->dwArgumentsOffset > 0)
{
lpService->ThreadParams.W.lpArgVector =
HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
if (lpService->ThreadParams.W.lpArgVector == NULL)
return ERROR_OUTOFMEMORY;
/* Get the size of the service start arguments */
if (ControlPacket->dwArgumentsCount > 0 &&
ControlPacket->dwArgumentsOffset != 0)
memcpy(lpService->ThreadParams.W.lpArgVector,
((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
lpArgW = lpService->ThreadParams.W.lpArgVector;
for (i = 0; i < lpService->ThreadParams.W.dwArgCount; i++)
{
*lpArgW = (LPWSTR)((ULONG_PTR)lpArgW + (ULONG_PTR)*lpArgW);
lpArgW++;
}
}
}
else
{
/* FIXME */
lpService->ThreadParams.A.dwArgCount = 0;
lpService->ThreadParams.A.lpArgVector = NULL;
#if 0
dwArgumentSize += (wcslen(...) + 1) * sizeof(WCHAR);
LPSTR *lpArgVector;
LPSTR Ptr;
LPSTR AnsiString;
DWORD AnsiLength;
AnsiLength = WideCharToMultiByte(CP_ACP,
0,
lpService->Arguments,
dwLength,
NULL,
0,
NULL,
NULL);
if (AnsiLength == 0)
return ERROR_INVALID_PARAMETER; /* ? */
AnsiString = HeapAlloc(GetProcessHeap(),
0,
AnsiLength + 1);
if (AnsiString == NULL)
return ERROR_OUTOFMEMORY;
WideCharToMultiByte(CP_ACP,
0,
lpService->Arguments,
dwLength,
AnsiString,
AnsiLength,
NULL,
NULL);
AnsiString[AnsiLength] = ANSI_NULL;
lpArgVector = HeapAlloc(GetProcessHeap(),
0,
(dwArgCount + 1) * sizeof(LPSTR));
if (lpArgVector == NULL)
{
HeapFree(GetProcessHeap(),
0,
AnsiString);
return ERROR_OUTOFMEMORY;
}
dwArgCount = 0;
Ptr = AnsiString;
while (*Ptr)
{
lpArgVector[dwArgCount] = Ptr;
dwArgCount++;
Ptr += (strlen(Ptr) + 1);
}
lpArgVector[dwArgCount] = NULL;
(lpService->ThreadParams.A.lpServiceMain)(dwArgCount, lpArgVector);
HeapFree(GetProcessHeap(),
0,
lpArgVector);
HeapFree(GetProcessHeap(),
0,
AnsiString);
#endif
}
lpService->Arguments = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwArgumentsSize + sizeof(WCHAR));
if (lpService->Arguments == NULL)
return ERROR_OUTOFMEMORY;
Ptr = lpService->Arguments;
/* Add the service name as first argument */
wcscpy(Ptr, pServiceName);
Ptr += (wcslen(pServiceName) + 1);
/* Add service start arguments */
if (ControlPacket->dwArgumentsCount > 0 &&
ControlPacket->dwArgumentsOffset != 0)
{
/* FIXME */
}
*Ptr = 0;
/* invoke the services entry point and implement the command loop */
/* Invoke the services entry point and implement the command loop */
ThreadHandle = CreateThread(NULL,
0,
ScServiceMainStub,
@ -405,7 +400,33 @@ ScStartService(PACTIVE_SERVICE lpService,
CREATE_SUSPENDED,
&ThreadId);
if (ThreadHandle == NULL)
{
/* Free the arguments vector */
if (lpService->bUnicode)
{
if (lpService->ThreadParams.W.lpArgVector != NULL)
{
HeapFree(GetProcessHeap(),
0,
lpService->ThreadParams.W.lpArgVector);
lpService->ThreadParams.W.lpArgVector = NULL;
lpService->ThreadParams.W.dwArgCount = 0;
}
}
else
{
if (lpService->ThreadParams.A.lpArgVector != NULL)
{
HeapFree(GetProcessHeap(),
0,
lpService->ThreadParams.A.lpArgVector);
lpService->ThreadParams.A.lpArgVector = NULL;
lpService->ThreadParams.A.dwArgCount = 0;
}
}
return ERROR_SERVICE_NO_THREAD;
}
ResumeThread(ThreadHandle);
CloseHandle(ThreadHandle);
@ -432,13 +453,6 @@ ScControlService(PACTIVE_SERVICE lpService,
(lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
}
if (ControlPacket->dwControl == SERVICE_CONTROL_STOP)
{
HeapFree(GetProcessHeap(),
0,
lpService->Arguments);
}
TRACE("ScControlService() done\n");
return ERROR_SUCCESS;
@ -820,7 +834,7 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
{
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].hServiceStatus = 0;
lpActiveServices[i].bUnicode = FALSE;
}
@ -915,7 +929,7 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
{
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].hServiceStatus = 0;
lpActiveServices[i].bUnicode = TRUE;
}