Author: hbelusca
Date: Mon Dec 5 16:22:30 2016
New Revision: 73430
URL:
http://svn.reactos.org/svn/reactos?rev=73430&view=rev
Log:
[ADVAPI32_APITEST]: Add a small helper lib 'svchlp' for common routines for
test-services embedded in api tests. Taken & heavily adapted from Jacek Caban's
services_service test and Thomas Faber's ServiceArgs.c (the latter will be able to use
'svchlp' when it'll be ready).
CORE-12414
Added:
trunk/rostests/apitests/advapi32/svchlp.c
- copied, changed from r73429, trunk/rostests/apitests/advapi32/ServiceArgs.c
trunk/rostests/apitests/advapi32/svchlp.h (with props)
Modified:
trunk/rostests/apitests/advapi32/CMakeLists.txt
Modified: trunk/rostests/apitests/advapi32/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/advapi32/CMakeLi…
==============================================================================
--- trunk/rostests/apitests/advapi32/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/rostests/apitests/advapi32/CMakeLists.txt [iso-8859-1] Mon Dec 5 16:22:30 2016
@@ -14,6 +14,7 @@
RtlEncryptMemory.c
SaferIdentifyLevel.c
ServiceArgs.c
+ svchlp.c
testlist.c)
add_executable(advapi32_apitest ${SOURCE})
Copied: trunk/rostests/apitests/advapi32/svchlp.c (from r73429,
trunk/rostests/apitests/advapi32/ServiceArgs.c)
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/advapi32/svchlp.…
==============================================================================
--- trunk/rostests/apitests/advapi32/ServiceArgs.c [iso-8859-1] (original)
+++ trunk/rostests/apitests/advapi32/svchlp.c [iso-8859-1] Mon Dec 5 16:22:30 2016
@@ -1,9 +1,16 @@
/*
* PROJECT: ReactOS api tests
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
- * PURPOSE: Test for service arguments
- * PROGRAMMER: Jacek Caban for CodeWeavers
+ * PURPOSE: Support helpers for embedded services inside api tests.
+ * PROGRAMMERS: Jacek Caban for CodeWeavers
* Thomas Faber <thomas.faber(a)reactos.org>
+ * Hermes Belusca-Maito
+ *
+ * NOTE: Room for improvements:
+ * - One test_runner managing 1 pipe for 1 service process that is shared
+ * by multiple services of type SERVICE_WIN32_SHARE_PROCESS.
+ * - Find a way to elegantly determine the registered service name inside
+ * the service process, without really passing it
*/
#include <apitest.h>
@@ -11,28 +18,25 @@
#include <winsvc.h>
#include <strsafe.h>
-static char **argv;
-static int argc;
-
-static HANDLE pipe_handle = INVALID_HANDLE_VALUE;
-static char service_nameA[100];
+static HANDLE hClientPipe = INVALID_HANDLE_VALUE;
+static WCHAR named_pipe_name[100]; // Shared: FIXME!
+
+static CHAR service_nameA[100];
static WCHAR service_nameW[100];
-static WCHAR named_pipe_name[100];
-
-/* Test process global variables */
-static SC_HANDLE scm_handle;
-static SERVICE_STATUS_HANDLE service_handle;
-
-static void send_msg(const char *type, const char *msg)
+
+
+/********** S E R V I C E ( C L I E N T ) M O D U L E S I D E *********/
+
+void send_msg(const char *type, const char *msg)
{
DWORD written = 0;
char buf[512];
StringCbPrintfA(buf, sizeof(buf), "%s:%s", type, msg);
- WriteFile(pipe_handle, buf, strlen(buf)+1, &written, NULL);
-}
-
-static inline void service_trace(const char *msg, ...)
+ WriteFile(hClientPipe, buf, strlen(buf)+1, &written, NULL);
+}
+
+void service_trace(const char *msg, ...)
{
va_list valist;
char buf[512];
@@ -44,10 +48,10 @@
send_msg("TRACE", buf);
}
-static void service_ok(int cnd, const char *msg, ...)
-{
- va_list valist;
- char buf[512];
+void service_ok(int cnd, const char *msg, ...)
+{
+ va_list valist;
+ char buf[512];
va_start(valist, msg);
StringCbVPrintfA(buf, sizeof(buf), msg, valist);
@@ -56,193 +60,81 @@
send_msg(cnd ? "OK" : "FAIL", buf);
}
-static VOID WINAPI service_handler(DWORD ctrl)
-{
- SERVICE_STATUS status;
-
- status.dwServiceType = SERVICE_WIN32;
- status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- status.dwWin32ExitCode = 0;
- status.dwServiceSpecificExitCode = 0;
- status.dwCheckPoint = 0;
- status.dwWaitHint = 0;
-
- switch(ctrl)
- {
- case SERVICE_CONTROL_STOP:
- status.dwCurrentState = SERVICE_STOP_PENDING;
- status.dwControlsAccepted = 0;
- SetServiceStatus(service_handle, &status);
- default:
- status.dwCurrentState = SERVICE_RUNNING;
- SetServiceStatus(service_handle, &status);
- }
-}
-
-static void service_main_common(void)
-{
- SERVICE_STATUS status;
+void service_process(BOOL (*start_service)(PCSTR, PCWSTR), int argc, char** argv)
+{
BOOL res;
- service_handle = RegisterServiceCtrlHandlerW(service_nameW, service_handler);
- service_ok(service_handle != NULL, "RegisterServiceCtrlHandler failed:
%lu\n", GetLastError());
- if (!service_handle)
- return;
-
- status.dwServiceType = SERVICE_WIN32;
- status.dwCurrentState = SERVICE_RUNNING;
- status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
- status.dwWin32ExitCode = 0;
- status.dwServiceSpecificExitCode = 0;
- status.dwCheckPoint = 0;
- status.dwWaitHint = 10000;
- res = SetServiceStatus(service_handle, &status);
- service_ok(res, "SetServiceStatus(SERVICE_RUNNING) failed: %lu",
GetLastError());
-
- Sleep(100);
-
- status.dwCurrentState = SERVICE_STOPPED;
- status.dwControlsAccepted = 0;
- res = SetServiceStatus(service_handle, &status);
- service_ok(res, "SetServiceStatus(SERVICE_STOPPED) failed: %lu",
GetLastError());
-}
-
-/*
- * A/W argument layout XP/2003:
- * [argv array of pointers][parameter 1][parameter 2]...[service name]
- *
- * A/W argument layout Vista:
- * [argv array of pointers][align to 8 bytes][parameter 1][parameter 2]...[service name]
- *
- * A/W argument layout Win7/8:
- * [argv array of pointers][service name]
- * [parameter 1][align to 4 bytes][parameter 2][align to 4 bytes]...
- *
- * Space for parameters and service name is always enough to store
- * the WCHAR version including null terminator.
- */
-
-static void WINAPI service_mainA(DWORD service_argc, char **service_argv)
-{
- int i;
- char *next_arg;
- char *next_arg_aligned;
-
- service_ok(service_argc == argc - 3, "service_argc = %d, expected %d",
service_argc, argc - 3);
- if (service_argc == argc - 3)
- {
- service_ok(!strcmp(service_argv[0], service_nameA), "service_argv[0] = %s,
expected %s", service_argv[0], service_nameA);
- service_ok(service_argv[0] == (char *)&service_argv[service_argc] ||
- service_argv[1] == (char *)&service_argv[service_argc] ||
- service_argv[1] == (char
*)(((ULONG_PTR)&service_argv[service_argc] + 7) & ~7), "service_argv[0] = %p,
[1] = %p, expected one of them to be %p", service_argv[0], service_argv[1],
&service_argv[service_argc]);
- //service_trace("service_argv[0] = %p", service_argv[0]);
- next_arg_aligned = next_arg = NULL;
- for (i = 1; i < service_argc; i++)
- {
- //service_trace("service_argv[%d] = %p", i, service_argv[i]);
- service_ok(!strcmp(service_argv[i], argv[i + 3]), "service_argv[%d] =
%s, expected %s", i, service_argv[i], argv[i + 3]);
- service_ok(next_arg == NULL ||
- service_argv[i] == next_arg ||
- service_argv[i] == next_arg_aligned, "service_argv[%d] = %p,
expected %p or %p", i, service_argv[i], next_arg, next_arg_aligned);
- next_arg = service_argv[i];
- next_arg += 2 * (strlen(next_arg) + 1);
- next_arg_aligned = (char *)(((ULONG_PTR)next_arg + 3) & ~3);
- }
- }
-
- service_main_common();
-}
-
-static void WINAPI service_mainW(DWORD service_argc, WCHAR **service_argv)
-{
- int i;
- WCHAR argW[32];
- WCHAR *next_arg;
- WCHAR *next_arg_aligned;
-
- service_ok(service_argc == argc - 3, "service_argc = %d, expected %d",
service_argc, argc - 3);
- if (service_argc == argc - 3)
- {
- service_ok(!wcscmp(service_argv[0], service_nameW), "service_argv[0] = %ls,
expected %ls", service_argv[0], service_nameW);
- service_ok(service_argv[0] == (WCHAR *)&service_argv[service_argc] ||
- service_argv[1] == (WCHAR *)&service_argv[service_argc] ||
- service_argv[1] == (WCHAR
*)(((ULONG_PTR)&service_argv[service_argc] + 7) & ~7), "service_argv[0] = %p,
[1] = %p, expected one of them to be %p", service_argv[0], service_argv[1],
&service_argv[service_argc]);
- //service_trace("service_argv[0] = %p", service_argv[0]);
- next_arg_aligned = next_arg = NULL;
- for (i = 1; i < service_argc; i++)
- {
- //service_trace("service_argv[%d] = %p", i, service_argv[i]);
- MultiByteToWideChar(CP_ACP, 0, argv[i + 3], -1, argW, _countof(argW));
- service_ok(!wcscmp(service_argv[i], argW), "service_argv[%d] = %ls,
expected %ls", i, service_argv[i], argW);
- service_ok(next_arg == NULL ||
- service_argv[i] == next_arg ||
- service_argv[i] == next_arg_aligned, "service_argv[%d] = %p,
expected %p or %p", i, service_argv[i], next_arg, next_arg_aligned);
- next_arg = service_argv[i];
- next_arg += wcslen(next_arg) + 1;
- next_arg_aligned = (WCHAR *)(((ULONG_PTR)next_arg + 3) & ~3);
- }
- }
-
- service_main_common();
-}
-
-static void service_process(BOOLEAN unicode)
-{
- BOOL res;
-
- SERVICE_TABLE_ENTRYA servtblA[] =
- {
- { service_nameA, service_mainA },
- { NULL, NULL }
- };
- SERVICE_TABLE_ENTRYW servtblW[] =
- {
- { service_nameW, service_mainW },
- { NULL, NULL }
- };
+ StringCbCopyA(service_nameA, sizeof(service_nameA), argv[2]);
+ MultiByteToWideChar(CP_ACP, 0, service_nameA, -1, service_nameW,
_countof(service_nameW));
+ StringCbPrintfW(named_pipe_name, sizeof(named_pipe_name),
L"\\\\.\\pipe\\%ls_pipe", service_nameW);
res = WaitNamedPipeW(named_pipe_name, NMPWAIT_USE_DEFAULT_WAIT);
if (!res)
return;
- pipe_handle = CreateFileW(named_pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
- if (pipe_handle == INVALID_HANDLE_VALUE)
+ hClientPipe = CreateFileW(named_pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hClientPipe == INVALID_HANDLE_VALUE)
return;
- //service_trace("Starting...");
- if (unicode)
- {
- res = StartServiceCtrlDispatcherW(servtblW);
- service_ok(res, "StartServiceCtrlDispatcherW failed: %lu\n",
GetLastError());
- }
- else
- {
- res = StartServiceCtrlDispatcherA(servtblA);
- service_ok(res, "StartServiceCtrlDispatcherA failed: %lu\n",
GetLastError());
- }
-
- CloseHandle(pipe_handle);
-}
-
-static SC_HANDLE register_service(PCWSTR extra_args)
-{
- WCHAR service_cmd[MAX_PATH+150];
+ service_trace("Service process starting...\n");
+ res = start_service(service_nameA, service_nameW);
+ service_trace("Service process stopped.\n");
+
+ CloseHandle(hClientPipe);
+}
+
+
+/*********** T E S T E R ( S E R V E R ) M O D U L E S I D E **********/
+
+SC_HANDLE register_service_exA(
+ SC_HANDLE scm_handle,
+ PCSTR test_name,
+ PCSTR service_name, // LPCSTR lpServiceName,
+ PCSTR extra_args OPTIONAL,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCSTR lpLoadOrderGroup OPTIONAL,
+ LPDWORD lpdwTagId OPTIONAL,
+ LPCSTR lpDependencies OPTIONAL,
+ LPCSTR lpServiceStartName OPTIONAL,
+ LPCSTR lpPassword OPTIONAL)
+{
SC_HANDLE service;
-
- GetModuleFileNameW(NULL, service_cmd, MAX_PATH);
-
- StringCbCatW(service_cmd, sizeof(service_cmd), L" ServiceArgs ");
- StringCbCatW(service_cmd, sizeof(service_cmd), service_nameW);
- StringCbCatW(service_cmd, sizeof(service_cmd), extra_args);
-
- trace("service_cmd \"%ls\"\n", service_cmd);
-
- service = CreateServiceW(scm_handle, service_nameW, service_nameW, GENERIC_ALL,
- SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE,
- service_cmd, NULL, NULL, NULL, NULL, NULL);
+ CHAR service_cmd[MAX_PATH+150];
+
+ /* Retrieve our full path */
+ if (!GetModuleFileNameA(NULL, service_cmd, MAX_PATH))
+ {
+ skip("GetModuleFileNameW failed with error %lu!\n", GetLastError());
+ return NULL;
+ }
+
+ /*
+ * Build up our custom command line. The first parameter is the test name,
+ * the second parameter is the flag used to decide whether we should start
+ * as a service.
+ */
+ StringCbCatA(service_cmd, sizeof(service_cmd), " ");
+ StringCbCatA(service_cmd, sizeof(service_cmd), test_name);
+ StringCbCatA(service_cmd, sizeof(service_cmd), " ");
+ StringCbCatA(service_cmd, sizeof(service_cmd), service_name);
+ if (extra_args)
+ {
+ StringCbCatA(service_cmd, sizeof(service_cmd), " ");
+ StringCbCatA(service_cmd, sizeof(service_cmd), extra_args);
+ }
+
+ trace("service_cmd \"%s\"\n", service_cmd);
+
+ service = CreateServiceA(scm_handle, service_name, service_name,
+ dwDesiredAccess, dwServiceType, dwStartType,
dwErrorControl,
+ service_cmd, lpLoadOrderGroup, lpdwTagId, lpDependencies,
+ lpServiceStartName, lpPassword);
if (!service && GetLastError() == ERROR_ACCESS_DENIED)
{
- skip("Not enough access right to create service\n");
+ skip("Not enough access right to create service.\n");
return NULL;
}
@@ -250,36 +142,124 @@
return service;
}
-static DWORD WINAPI pipe_thread(void *arg)
-{
- char buf[512];
+SC_HANDLE register_service_exW(
+ SC_HANDLE scm_handle,
+ PCWSTR test_name,
+ PCWSTR service_name, // LPCWSTR lpServiceName,
+ PCWSTR extra_args OPTIONAL,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCWSTR lpLoadOrderGroup OPTIONAL,
+ LPDWORD lpdwTagId OPTIONAL,
+ LPCWSTR lpDependencies OPTIONAL,
+ LPCWSTR lpServiceStartName OPTIONAL,
+ LPCWSTR lpPassword OPTIONAL)
+{
+ SC_HANDLE service;
+ WCHAR service_cmd[MAX_PATH+150];
+
+ /* Retrieve our full path */
+ if (!GetModuleFileNameW(NULL, service_cmd, MAX_PATH))
+ {
+ skip("GetModuleFileNameW failed with error %lu!\n", GetLastError());
+ return NULL;
+ }
+
+ /*
+ * Build up our custom command line. The first parameter is the test name,
+ * the second parameter is the flag used to decide whether we should start
+ * as a service.
+ */
+ StringCbCatW(service_cmd, sizeof(service_cmd), L" ");
+ StringCbCatW(service_cmd, sizeof(service_cmd), test_name);
+ StringCbCatW(service_cmd, sizeof(service_cmd), L" ");
+ StringCbCatW(service_cmd, sizeof(service_cmd), service_name);
+ if (extra_args)
+ {
+ StringCbCatW(service_cmd, sizeof(service_cmd), L" ");
+ StringCbCatW(service_cmd, sizeof(service_cmd), extra_args);
+ }
+
+ trace("service_cmd \"%ls\"\n", service_cmd);
+
+ service = CreateServiceW(scm_handle, service_name, service_name,
+ dwDesiredAccess, dwServiceType, dwStartType,
dwErrorControl,
+ service_cmd, lpLoadOrderGroup, lpdwTagId, lpDependencies,
+ lpServiceStartName, lpPassword);
+ if (!service && GetLastError() == ERROR_ACCESS_DENIED)
+ {
+ skip("Not enough access right to create service.\n");
+ return NULL;
+ }
+
+ ok(service != NULL, "CreateService failed: %lu\n", GetLastError());
+ return service;
+}
+
+SC_HANDLE register_serviceA(
+ SC_HANDLE scm_handle,
+ PCSTR test_name,
+ PCSTR service_name,
+ PCSTR extra_args OPTIONAL)
+{
+ return register_service_exA(scm_handle, test_name, service_name, extra_args,
+ SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DEMAND_START,
+ SERVICE_ERROR_IGNORE,
+ NULL, NULL, NULL, NULL, NULL);
+}
+
+SC_HANDLE register_serviceW(
+ SC_HANDLE scm_handle,
+ PCWSTR test_name,
+ PCWSTR service_name,
+ PCWSTR extra_args OPTIONAL)
+{
+ return register_service_exW(scm_handle, test_name, service_name, extra_args,
+ SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DEMAND_START,
+ SERVICE_ERROR_IGNORE,
+ NULL, NULL, NULL, NULL, NULL);
+}
+
+static DWORD WINAPI pipe_thread(void *param)
+{
+ HANDLE hServerPipe = (HANDLE)param;
DWORD read;
BOOL res;
-
- res = ConnectNamedPipe(pipe_handle, NULL);
+ char buf[512];
+
+ // printf("pipe_thread -- ConnectNamedPipe...\n");
+ res = ConnectNamedPipe(hServerPipe, NULL);
ok(res || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe failed:
%lu\n", GetLastError());
+ // printf("pipe_thread -- ConnectNamedPipe ok\n");
while (1)
{
- res = ReadFile(pipe_handle, buf, sizeof(buf), &read, NULL);
+ res = ReadFile(hServerPipe, buf, sizeof(buf), &read, NULL);
if (!res)
{
ok(GetLastError() == ERROR_BROKEN_PIPE || GetLastError() ==
ERROR_INVALID_HANDLE,
"ReadFile failed: %lu\n", GetLastError());
+ // printf("pipe_thread -- break loop\n");
break;
}
if (!strncmp(buf, "TRACE:", 6))
{
- trace("service trace: %s\n", buf+6);
+ trace("service trace: %s", buf+6);
}
else if (!strncmp(buf, "OK:", 3))
{
- ok(1, "service: %s\n", buf+3);
+ ok(1, "service: %s", buf+3);
}
else if (!strncmp(buf, "FAIL:", 5))
{
- ok(0, "service: %s\n", buf+5);
+ ok(0, "service: %s", buf+5);
}
else
{
@@ -287,189 +267,52 @@
}
}
- DisconnectNamedPipe(pipe_handle);
- //trace("pipe disconnected\n");
+ // printf("pipe_thread -- DisconnectNamedPipe\n");
+
+ /*
+ * Flush the pipe to allow the client to read
+ * the pipe's contents before disconnecting.
+ */
+ FlushFileBuffers(hServerPipe);
+
+ DisconnectNamedPipe(hServerPipe);
+ trace("pipe disconnected\n");
return 0;
}
-static void test_startA(SC_HANDLE service_handle, int service_argc, const char
**service_argv)
-{
- SERVICE_STATUS status;
- BOOL res;
-
- res = StartServiceA(service_handle, service_argc, service_argv);
- ok(res, "StartService failed: %lu\n", GetLastError());
- if (!res)
- return;
-
- do
- {
- Sleep(100);
- ZeroMemory(&status, sizeof(status));
- res = QueryServiceStatus(service_handle, &status);
- } while (res && status.dwCurrentState != SERVICE_STOPPED);
- ok(res, "QueryServiceStatus failed: %lu\n", GetLastError());
- ok(status.dwCurrentState == SERVICE_STOPPED, "status.dwCurrentState =
%lx\n", status.dwCurrentState);
-}
-
-static void test_startW(SC_HANDLE service_handle, int service_argc, const WCHAR
**service_argv)
-{
- SERVICE_STATUS status;
- BOOL res;
-
- res = StartServiceW(service_handle, service_argc, service_argv);
- ok(res, "StartService failed: %lu\n", GetLastError());
- if (!res)
- return;
-
- do
- {
- Sleep(100);
- ZeroMemory(&status, sizeof(status));
- res = QueryServiceStatus(service_handle, &status);
- } while (res && status.dwCurrentState != SERVICE_STOPPED);
- ok(res, "QueryServiceStatus failed: %lu\n", GetLastError());
- ok(status.dwCurrentState == SERVICE_STOPPED, "status.dwCurrentState =
%lx\n", status.dwCurrentState);
-}
-
-static void test_runner(BOOLEAN unicode, PCWSTR extra_args, int service_argc, void
*service_argv)
-{
- HANDLE thread;
- SC_HANDLE service_handle;
- BOOL res;
+void test_runner(void (*run_test)(PCSTR, PCWSTR, void*), void *param)
+{
+ HANDLE hServerPipe = INVALID_HANDLE_VALUE;
+ HANDLE hThread;
StringCbPrintfW(service_nameW, sizeof(service_nameW),
L"WineTestService%lu", GetTickCount());
WideCharToMultiByte(CP_ACP, 0, service_nameW, -1, service_nameA,
_countof(service_nameA), NULL, NULL);
//trace("service_name: %ls\n", service_nameW);
StringCbPrintfW(named_pipe_name, sizeof(named_pipe_name),
L"\\\\.\\pipe\\%ls_pipe", service_nameW);
- pipe_handle = CreateNamedPipeW(named_pipe_name, PIPE_ACCESS_INBOUND,
+ hServerPipe = CreateNamedPipeW(named_pipe_name, PIPE_ACCESS_INBOUND,
PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, 10,
2048, 2048, 10000, NULL);
- ok(pipe_handle != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n",
GetLastError());
- if (pipe_handle == INVALID_HANDLE_VALUE)
+ ok(hServerPipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n",
GetLastError());
+ if (hServerPipe == INVALID_HANDLE_VALUE)
return;
- thread = CreateThread(NULL, 0, pipe_thread, NULL, 0, NULL);
- ok(thread != NULL, "CreateThread failed: %lu\n", GetLastError());
- if (!thread)
- return;
-
- service_handle = register_service(extra_args);
- if (!service_handle)
- return;
-
- //trace("starting...\n");
-
- if (unicode)
- test_startW(service_handle, service_argc, service_argv);
- else
- test_startA(service_handle, service_argc, service_argv);
-
- res = DeleteService(service_handle);
- ok(res, "DeleteService failed: %lu\n", GetLastError());
-
- CloseServiceHandle(service_handle);
-
- ok(WaitForSingleObject(thread, 10000) == WAIT_OBJECT_0, "Timeout waiting for
thread\n");
- CloseHandle(thread);
- CloseHandle(pipe_handle);
-}
-
-START_TEST(ServiceArgs)
-{
- argc = winetest_get_mainargs(&argv);
-
- scm_handle = OpenSCManagerW(NULL, NULL, GENERIC_ALL);
- ok(scm_handle != NULL, "OpenSCManager failed: %lu\n", GetLastError());
- if (!scm_handle)
- {
- skip("Failed to open service control manager. Skipping test\n");
- return;
- }
-
- if (argc < 3)
- {
- char *service_argvA[10];
- WCHAR *service_argvW[10];
-
- test_runner(FALSE, L" A", 0, NULL);
- test_runner(FALSE, L" W", 0, NULL);
- test_runner(TRUE, L" A", 0, NULL);
- test_runner(TRUE, L" W", 0, NULL);
-
- service_argvA[0] = "x";
- service_argvW[0] = L"x";
- test_runner(FALSE, L" A x", 1, service_argvA);
- test_runner(FALSE, L" W x", 1, service_argvA);
- test_runner(TRUE, L" A x", 1, service_argvW);
- test_runner(TRUE, L" W x", 1, service_argvW);
-
- service_argvA[1] = "y";
- service_argvW[1] = L"y";
- test_runner(FALSE, L" A x y", 2, service_argvA);
- test_runner(FALSE, L" W x y", 2, service_argvA);
- test_runner(TRUE, L" A x y", 2, service_argvW);
- test_runner(TRUE, L" W x y", 2, service_argvW);
-
- service_argvA[0] = "ab";
- service_argvW[0] = L"ab";
- test_runner(FALSE, L" A ab y", 2, service_argvA);
- test_runner(FALSE, L" W ab y", 2, service_argvA);
- test_runner(TRUE, L" A ab y", 2, service_argvW);
- test_runner(TRUE, L" W ab y", 2, service_argvW);
-
- service_argvA[0] = "abc";
- service_argvW[0] = L"abc";
- test_runner(FALSE, L" A abc y", 2, service_argvA);
- test_runner(FALSE, L" W abc y", 2, service_argvA);
- test_runner(TRUE, L" A abc y", 2, service_argvW);
- test_runner(TRUE, L" W abc y", 2, service_argvW);
-
- service_argvA[0] = "abcd";
- service_argvW[0] = L"abcd";
- test_runner(FALSE, L" A abcd y", 2, service_argvA);
- test_runner(FALSE, L" W abcd y", 2, service_argvA);
- test_runner(TRUE, L" A abcd y", 2, service_argvW);
- test_runner(TRUE, L" W abcd y", 2, service_argvW);
-
- service_argvA[0] = "abcde";
- service_argvW[0] = L"abcde";
- test_runner(FALSE, L" A abcde y", 2, service_argvA);
- test_runner(FALSE, L" W abcde y", 2, service_argvA);
- test_runner(TRUE, L" A abcde y", 2, service_argvW);
- test_runner(TRUE, L" W abcde y", 2, service_argvW);
-
- service_argvA[0] = "abcdef";
- service_argvW[0] = L"abcdef";
- test_runner(FALSE, L" A abcdef y", 2, service_argvA);
- test_runner(FALSE, L" W abcdef y", 2, service_argvA);
- test_runner(TRUE, L" A abcdef y", 2, service_argvW);
- test_runner(TRUE, L" W abcdef y", 2, service_argvW);
-
- service_argvA[0] = "abcdefg";
- service_argvW[0] = L"abcdefg";
- test_runner(FALSE, L" A abcdefg y", 2, service_argvA);
- test_runner(FALSE, L" W abcdefg y", 2, service_argvA);
- test_runner(TRUE, L" A abcdefg y", 2, service_argvW);
- test_runner(TRUE, L" W abcdefg y", 2, service_argvW);
-
- service_argvA[0] = "";
- service_argvW[0] = L"";
- test_runner(FALSE, L" A \"\" y", 2, service_argvA);
- test_runner(FALSE, L" W \"\" y", 2, service_argvA);
- test_runner(TRUE, L" A \"\" y", 2, service_argvW);
- test_runner(TRUE, L" W \"\" y", 2, service_argvW);
- }
- else
- {
- strcpy(service_nameA, argv[2]);
- MultiByteToWideChar(CP_ACP, 0, service_nameA, -1, service_nameW,
_countof(service_nameW));
- StringCbPrintfW(named_pipe_name, sizeof(named_pipe_name),
L"\\\\.\\pipe\\%ls_pipe", service_nameW);
- if (!strcmp(argv[3], "A"))
- service_process(FALSE);
- else
- service_process(TRUE);
- }
-
- CloseServiceHandle(scm_handle);
-}
+ hThread = CreateThread(NULL, 0, pipe_thread, (LPVOID)hServerPipe, 0, NULL);
+ ok(hThread != NULL, "CreateThread failed: %lu\n", GetLastError());
+ if (!hThread)
+ goto Quit;
+
+ run_test(service_nameA, service_nameW, param);
+
+ ok(WaitForSingleObject(hThread, 10000) == WAIT_OBJECT_0, "Timeout waiting for
thread\n");
+
+Quit:
+ if (hThread)
+ {
+ /* Be sure to kill the thread if it did not already terminate */
+ TerminateThread(hThread, 0);
+ CloseHandle(hThread);
+ }
+
+ if (hServerPipe != INVALID_HANDLE_VALUE)
+ CloseHandle(hServerPipe);
+}
Added: trunk/rostests/apitests/advapi32/svchlp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/advapi32/svchlp.…
==============================================================================
--- trunk/rostests/apitests/advapi32/svchlp.h (added)
+++ trunk/rostests/apitests/advapi32/svchlp.h [iso-8859-1] Mon Dec 5 16:22:30 2016
@@ -0,0 +1,73 @@
+/*
+ * PROJECT: ReactOS api tests
+ * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Support helpers for embedded services inside api tests.
+ * PROGRAMMERS: Jacek Caban for CodeWeavers
+ * Thomas Faber <thomas.faber(a)reactos.org>
+ * Hermes Belusca-Maito
+ */
+
+// #include <apitest.h>
+
+
+/********** S E R V I C E ( C L I E N T ) M O D U L E S I D E *********/
+
+void send_msg(const char *type, const char *msg);
+void service_trace(const char *msg, ...);
+void service_ok(int cnd, const char *msg, ...);
+void service_process(BOOL (*start_service)(PCSTR, PCWSTR), int argc, char** argv);
+
+
+/*********** T E S T E R ( S E R V E R ) M O D U L E S I D E **********/
+
+SC_HANDLE register_service_exA(
+ SC_HANDLE scm_handle,
+ PCSTR test_name,
+ PCSTR service_name, // LPCSTR lpServiceName,
+ PCSTR extra_args OPTIONAL,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCSTR lpLoadOrderGroup OPTIONAL,
+ LPDWORD lpdwTagId OPTIONAL,
+ LPCSTR lpDependencies OPTIONAL,
+ LPCSTR lpServiceStartName OPTIONAL,
+ LPCSTR lpPassword OPTIONAL);
+
+SC_HANDLE register_service_exW(
+ SC_HANDLE scm_handle,
+ PCWSTR test_name,
+ PCWSTR service_name, // LPCWSTR lpServiceName,
+ PCWSTR extra_args OPTIONAL,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCWSTR lpLoadOrderGroup OPTIONAL,
+ LPDWORD lpdwTagId OPTIONAL,
+ LPCWSTR lpDependencies OPTIONAL,
+ LPCWSTR lpServiceStartName OPTIONAL,
+ LPCWSTR lpPassword OPTIONAL);
+
+SC_HANDLE register_serviceA(
+ SC_HANDLE scm_handle,
+ PCSTR test_name,
+ PCSTR service_name,
+ PCSTR extra_args OPTIONAL);
+
+SC_HANDLE register_serviceW(
+ SC_HANDLE scm_handle,
+ PCWSTR test_name,
+ PCWSTR service_name,
+ PCWSTR extra_args OPTIONAL);
+
+#ifdef UNICODE
+#define register_service_ex register_service_exW
+#define register_service register_serviceW
+#else
+#define register_service_ex register_service_exA
+#define register_service register_serviceA
+#endif
+
+void test_runner(void (*run_test)(PCSTR, PCWSTR, void*), void *param);
Propchange: trunk/rostests/apitests/advapi32/svchlp.h
------------------------------------------------------------------------------
svn:eol-style = native