ReactOS  0.4.13-dev-39-g8b6696f
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 
17 static 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  {
41  status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
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 
67 static void WINAPI
68 service_main(DWORD dwArgc, LPWSTR* lpszArgv)
69 {
70  // SERVICE_STATUS_HANDLE status_handle;
71  LPWSTR lpEnvironment, lpEnvStr;
72  DWORD dwSize;
73  PTEB Teb;
74 
75  UNREFERENCED_PARAMETER(dwArgc);
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;
123  PWSTR Buffer;
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 
159  res = StartServiceCtrlDispatcherW(servtbl);
160  service_ok(res, "StartServiceCtrlDispatcherW failed: %lu\n", GetLastError());
161  return res;
162 }
163 
164 
165 /*** Tester part of the test ***/
166 
167 static 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);
211  res = QueryServiceStatus(hService, &ServiceStatus);
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);
254  res = QueryServiceStatus(hService, &ServiceStatus);
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 
270 Cleanup:
271  if (hService)
272  {
273  res = DeleteService(hService);
274  ok(res, "DeleteService failed: %lu\n", GetLastError());
275  CloseServiceHandle(hService);
276  }
277 
278  if (hSC)
279  CloseServiceHandle(hSC);
280 }
281 
282 START_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 void test_runner(BOOLEAN unicode, PCWSTR extra_args, int service_argc, void *service_argv)
Definition: ServiceArgs.c:334
static int argc
Definition: ServiceArgs.c:12
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define trace(...)
Definition: kmt_test.h:217
#define SERVICE_ERROR_IGNORE
Definition: cmtypes.h:979
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2697
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
DWORD dwCurrentState
Definition: winsvc.h:100
static SERVICE_STATUS_HANDLE status_handle
Definition: ServiceEnv.c:15
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
uint16_t * PWSTR
Definition: typedefs.h:54
static void report_service_status(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
Definition: ServiceEnv.c:18
#define SERVICE_INTERACTIVE_PROCESS
Definition: cmtypes.h:965
static void service_process(BOOLEAN unicode)
Definition: ServiceArgs.c:188
static SERVICE_STATUS ServiceStatus
Definition: dcomlaunch.c:27
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
#define SERVICE_START_PENDING
Definition: winsvc.h:22
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc)
Definition: sctrl.c:732
static void my_test_server(PCSTR service_nameA, PCWSTR service_nameW, void *param)
Definition: ServiceEnv.c:168
#define SERVICE_ALL_ACCESS
Definition: winsvc.h:62
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:916
#define argv
Definition: mplay32.c:18
#define NO_ERROR
Definition: dderror.h:5
BOOL WINAPI StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
Definition: sctrl.c:1123
#define DWORD
Definition: nt_native.h:44
#define ERROR_SERVICE_NOT_ACTIVE
Definition: winerror.h:613
static BOOL start_service(PCSTR service_nameA, PCWSTR service_nameW)
Definition: ServiceEnv.c:149
#define SERVICE_NO_CHANGE
Definition: winsvc.h:20
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:986
#define SERVICE_STOPPED
Definition: winsvc.h:21
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define SERVICE_RUNNING
Definition: winsvc.h:24
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:480
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:577
smooth NULL
Definition: ftsmooth.c:416
void * PVOID
Definition: retypes.h:9
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:960
void service_trace(const char *msg,...)
Definition: svchlp.c:36
#define ctrl
Definition: input.c:1669
#define ok(value,...)
Definition: CComObject.cpp:34
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs, LPCWSTR *lpServiceArgVectors)
Definition: scm.c:2923
static void service_ok(int cnd, const char *msg,...)
Definition: ServiceArgs.c:46
BOOL WINAPI FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
Definition: environ.c:389
GLfloat param
Definition: glext.h:5796
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2788
int winetest_get_mainargs(char ***pargv)
static const WCHAR L[]
Definition: oid.c:1250
SC_HANDLE WINAPI OpenSCManagerW(LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess)
Definition: scm.c:2011
START_TEST(ServiceEnv)
Definition: ServiceEnv.c:282
static const WCHAR Cleanup[]
Definition: register.c:80
static VOID WINAPI service_handler(DWORD ctrl)
Definition: ServiceEnv.c:55
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
Definition: compat.h:484
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
#define GetModuleHandle
Definition: winbase.h:3641
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define skip(...)
Definition: CString.cpp:57
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:619
static char service_nameA[100]
Definition: ServiceArgs.c:15
#define SC_MANAGER_ALL_ACCESS
Definition: winsvc.h:13
LPWSTR WINAPI GetEnvironmentStringsW(VOID)
Definition: environ.c:344
static WCHAR service_nameW[100]
Definition: ServiceArgs.c:16
GLuint res
Definition: glext.h:9613
unsigned int ULONG
Definition: retypes.h:1
#define GetProcAddress(x, y)
Definition: compat.h:410
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
const char * PCSTR
Definition: typedefs.h:51
static void WINAPI service_main(DWORD dwArgc, LPWSTR *lpszArgv)
Definition: ServiceEnv.c:68
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define SERVICE_DEMAND_START
Definition: cmtypes.h:976
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:412
static SERVICE_STATUS status
Definition: service.c:31
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
DWORD WINAPI GetCurrentProcessId(VOID)
Definition: proc.c:1188
static DWORD ServiceTag
Definition: database.c:34
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
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
Definition: ps.c:97