ReactOS 0.4.15-dev-7953-g1f49173
ServiceEnv.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for service process environment block
5 * PROGRAMMER: Hermes Belusca-Maito
6 */
7
8#include "precomp.h"
9
10#include "svchlp.h"
11
12
13/*** Service part of the test ***/
14
16
17static void
19 DWORD dwWin32ExitCode,
20 DWORD dwWaitHint)
21{
22 BOOL res;
24
25 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
26 status.dwCurrentState = dwCurrentState;
27 status.dwWin32ExitCode = dwWin32ExitCode;
28 status.dwWaitHint = dwWaitHint;
29
30 status.dwServiceSpecificExitCode = 0;
31 status.dwCheckPoint = 0;
32
33 if ( (dwCurrentState == SERVICE_START_PENDING) ||
34 (dwCurrentState == SERVICE_STOP_PENDING) ||
35 (dwCurrentState == SERVICE_STOPPED) )
36 {
37 status.dwControlsAccepted = 0;
38 }
39 else
40 {
42 }
43
44#if 0
45 if ( (dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED) )
46 status.dwCheckPoint = 0;
47 else
48 status.dwCheckPoint = dwCheckPoint++;
49#endif
50
52 service_ok(res, "SetServiceStatus(%d) failed: %lu\n", dwCurrentState, GetLastError());
53}
54
56{
57 switch(ctrl)
58 {
62 default:
64 }
65}
66
67static void WINAPI
68service_main(DWORD dwArgc, LPWSTR* lpszArgv)
69{
70 // SERVICE_STATUS_HANDLE status_handle;
71 LPWSTR lpEnvironment, lpEnvStr;
73 PTEB Teb;
74
76 UNREFERENCED_PARAMETER(lpszArgv);
77
78 /* Register our service for control (lpszArgv[0] holds the service name) */
80 service_ok(status_handle != NULL, "RegisterServiceCtrlHandler failed: %lu\n", GetLastError());
81 if (!status_handle)
82 return;
83
84 /* Report SERVICE_RUNNING status */
86
87 /* Display our current environment for informative purposes */
88 lpEnvironment = GetEnvironmentStringsW();
89 lpEnvStr = lpEnvironment;
90 while (*lpEnvStr)
91 {
92 service_trace("%S\n", lpEnvStr);
93 lpEnvStr += wcslen(lpEnvStr) + 1;
94 }
95 FreeEnvironmentStringsW(lpEnvironment);
96
97 /* Check the presence of the user-related environment variables */
98 dwSize = GetEnvironmentVariableW(L"ALLUSERSPROFILE", NULL, 0);
99 service_ok(dwSize != 0, "ALLUSERSPROFILE envvar not found, or GetEnvironmentVariableW failed: %lu\n", GetLastError());
100 dwSize = GetEnvironmentVariableW(L"USERPROFILE", NULL, 0);
101 service_ok(dwSize != 0, "USERPROFILE envvar not found, or GetEnvironmentVariableW failed: %lu\n", GetLastError());
102#if 0 // May not always exist
103 dwSize = GetEnvironmentVariableW(L"USERNAME", NULL, 0);
104 service_ok(dwSize != 0, "USERNAME envvar not found, or GetEnvironmentVariableW failed: %lu\n", GetLastError());
105#endif
106
107 Teb = NtCurrentTeb();
108 service_ok(Teb->SubProcessTag != 0, "SubProcessTag is not defined!\n");
109 if (Teb->SubProcessTag != 0)
110 {
111 ULONG (NTAPI *_I_QueryTagInformation)(PVOID, DWORD, PVOID) = (PVOID)GetProcAddress(GetModuleHandle("advapi32.dll"), "I_QueryTagInformation");
112 if (_I_QueryTagInformation != NULL)
113 {
114 /* IN/OUT parameter structure for I_QueryTagInformation() function
115 * See: https://wj32.org/wp/2010/03/30/howto-use-i_querytaginformation/
116 * See: https://github.com/processhacker/processhacker/blob/master/phnt/include/subprocesstag.h
117 */
118 struct
119 {
122 ULONG TagType;
124 } ServiceQuery;
125
126 /* Set our input parameters */
127 ServiceQuery.ProcessId = GetCurrentProcessId();
128 ServiceQuery.ServiceTag = Teb->SubProcessTag;
129 ServiceQuery.TagType = 0;
130 ServiceQuery.Buffer = NULL;
131 /* Call ADVAPI32 to query the correctness of our tag */
132 _I_QueryTagInformation(NULL, 1, &ServiceQuery);
133
134 /* If buffer is not NULL, call succeed */
135 if (ServiceQuery.Buffer != NULL)
136 {
137 /* It should match our service name */
138 service_ok(wcscmp(lpszArgv[0], ServiceQuery.Buffer) == 0, "Mismatching info: %S - %S\n", lpszArgv[0], ServiceQuery.Buffer);
139 service_ok(ServiceQuery.TagType == 1, "Invalid tag type: %x\n", ServiceQuery.TagType);
140 LocalFree(ServiceQuery.Buffer);
141 }
142 }
143 }
144
145 /* Work is done */
147}
148
150{
151 BOOL res;
152
153 SERVICE_TABLE_ENTRYW servtbl[] =
154 {
156 { NULL, NULL }
157 };
158
160 service_ok(res, "StartServiceCtrlDispatcherW failed: %lu\n", GetLastError());
161 return res;
162}
163
164
165/*** Tester part of the test ***/
166
167static void
170 void *param)
171{
172 BOOL res;
173 SC_HANDLE hSC = NULL;
174 SC_HANDLE hService = NULL;
176
177 /* Open the SCM */
179 if (!hSC)
180 {
181 skip("OpenSCManagerW failed with error %lu!\n", GetLastError());
182 return;
183 }
184
185 /* First create ourselves as a service running in the default LocalSystem account */
186 hService = register_service_exW(hSC, L"ServiceEnv", service_nameW, NULL,
191 NULL, NULL, NULL,
192 NULL, NULL);
193 if (!hService)
194 {
195 skip("CreateServiceW failed with error %lu!\n", GetLastError());
196 goto Cleanup;
197 }
198
199 /* Start it */
200 if (!StartServiceW(hService, 0, NULL))
201 {
202 skip("StartServiceW failed with error %lu!\n", GetLastError());
203 goto Cleanup;
204 }
205
206 /* Wait for the service to stop by itself */
207 do
208 {
209 Sleep(100);
213 ok(res, "QueryServiceStatus failed: %lu\n", GetLastError());
214 ok(ServiceStatus.dwCurrentState == SERVICE_STOPPED, "ServiceStatus.dwCurrentState = %lx\n", ServiceStatus.dwCurrentState);
215
216 /* Be sure the service is really stopped */
221 {
222 skip("ControlService failed with error %lu!\n", GetLastError());
223 goto Cleanup;
224 }
225
226#if 0
227 trace("Service stopped. Going to restart it...\n");
228
229 /* Now change the service configuration to make it start under the NetworkService account */
230 if (!ChangeServiceConfigW(hService,
234 NULL, NULL, NULL, NULL,
235 L"NT AUTHORITY\\NetworkService", L"",
236 NULL))
237 {
238 skip("ChangeServiceConfigW failed with error %lu!\n", GetLastError());
239 goto Cleanup;
240 }
241
242 /* Start it */
243 if (!StartServiceW(hService, 0, NULL))
244 {
245 skip("StartServiceW failed with error %lu!\n", GetLastError());
246 goto Cleanup;
247 }
248
249 /* Wait for the service to stop by itself */
250 do
251 {
252 Sleep(100);
256 ok(res, "QueryServiceStatus failed: %lu\n", GetLastError());
257 ok(ServiceStatus.dwCurrentState == SERVICE_STOPPED, "ServiceStatus.dwCurrentState = %lx\n", ServiceStatus.dwCurrentState);
258
259 /* Be sure the service is really stopped */
264 {
265 skip("ControlService failed with error %lu!\n", GetLastError());
266 goto Cleanup;
267 }
268#endif
269
270Cleanup:
271 if (hService)
272 {
273 res = DeleteService(hService);
274 ok(res, "DeleteService failed: %lu\n", GetLastError());
275 CloseServiceHandle(hService);
276 }
277
278 if (hSC)
280}
281
282START_TEST(ServiceEnv)
283{
284 int argc;
285 char** argv;
286 PTEB Teb;
287
288 /* Check whether this test is started as a separated service process */
290 if (argc >= 3)
291 {
293 return;
294 }
295
296 Teb = NtCurrentTeb();
297 ok(Teb->SubProcessTag == 0, "SubProcessTag is defined: %p\n", Teb->SubProcessTag);
298
299 /* We are started as the real test */
301 // trace("Returned from test_runner\n");
302}
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
static void service_ok(int cnd, const char *msg,...)
Definition: ServiceArgs.c:46
static void test_runner(BOOLEAN unicode, PCWSTR extra_args, int service_argc, void *service_argv)
Definition: ServiceArgs.c:334
static char service_nameA[100]
Definition: ServiceArgs.c:15
static WCHAR service_nameW[100]
Definition: ServiceArgs.c:16
static void service_process(BOOLEAN unicode)
Definition: ServiceArgs.c:188
static int argc
Definition: ServiceArgs.c:12
static BOOL start_service(PCSTR service_nameA, PCWSTR service_nameW)
Definition: ServiceEnv.c:149
static VOID WINAPI service_handler(DWORD ctrl)
Definition: ServiceEnv.c:55
static void WINAPI service_main(DWORD dwArgc, LPWSTR *lpszArgv)
Definition: ServiceEnv.c:68
static void my_test_server(PCSTR service_nameA, PCWSTR service_nameW, void *param)
Definition: ServiceEnv.c:168
static SERVICE_STATUS_HANDLE status_handle
Definition: ServiceEnv.c:15
static void report_service_status(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
Definition: ServiceEnv.c:18
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
static SERVICE_STATUS ServiceStatus
Definition: browser.c:22
static DWORD ServiceTag
Definition: database.c:34
Definition: bufpool.h:45
#define NO_ERROR
Definition: dderror.h:5
#define NULL
Definition: types.h:112
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#define GetProcAddress(x, y)
Definition: compat.h:753
BOOL WINAPI FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
Definition: environ.c:389
static const WCHAR Cleanup[]
Definition: register.c:80
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2711
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint res
Definition: glext.h:9613
GLfloat param
Definition: glext.h:5796
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define NtCurrentTeb
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define ctrl
Definition: input.c:1756
#define argv
Definition: mplay32.c:18
#define DWORD
Definition: nt_native.h:44
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define L(x)
Definition: ntvdm.h:50
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2845
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:921
SC_HANDLE WINAPI OpenSCManagerW(LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess)
Definition: scm.c:2068
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:622
BOOL WINAPI ChangeServiceConfigW(SC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies, LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
Definition: scm.c:482
BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs, LPCWSTR *lpServiceArgVectors)
Definition: scm.c:2980
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:580
BOOL WINAPI StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
Definition: sctrl.c:1134
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc)
Definition: sctrl.c:742
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:997
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
int winetest_get_mainargs(char ***pargv)
DWORD dwCurrentState
Definition: winsvc.h:100
Definition: compat.h:836
Definition: ps.c:97
void service_trace(const char *msg,...)
Definition: svchlp.c:36
SC_HANDLE register_service_exW(SC_HANDLE scm_handle, PCWSTR test_name, PCWSTR service_name, 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)
Definition: svchlp.c:142
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG
Definition: typedefs.h:59
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
#define GetModuleHandle
Definition: winbase.h:3827
LPWSTR WINAPI GetEnvironmentStringsW(void)
Definition: environ.c:344
#define WINAPI
Definition: msvc.h:6
#define ERROR_SERVICE_NOT_ACTIVE
Definition: winerror.h:613
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_ALL_ACCESS
Definition: winsvc.h:62
#define SERVICE_NO_CHANGE
Definition: winsvc.h:20
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
#define SC_MANAGER_ALL_ACCESS
Definition: winsvc.h:13
#define SERVICE_DEMAND_START
Definition: cmtypes.h:978
#define SERVICE_INTERACTIVE_PROCESS
Definition: cmtypes.h:967
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:962
#define SERVICE_ERROR_IGNORE
Definition: cmtypes.h:981
WCHAR * LPWSTR
Definition: xmlstorage.h:184