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

View file

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