ReactOS 0.4.16-dev-112-g52265ae
ServiceEnv.c File Reference
#include "precomp.h"
#include "svchlp.h"
Include dependency graph for ServiceEnv.c:

Go to the source code of this file.

Functions

static void report_service_status (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
 
static VOID WINAPI service_handler (DWORD ctrl)
 
static void WINAPI service_main (DWORD dwArgc, LPWSTR *lpszArgv)
 
static BOOL start_service (PCSTR service_nameA, PCWSTR service_nameW)
 
static void my_test_server (PCSTR service_nameA, PCWSTR service_nameW, void *param)
 
 START_TEST (ServiceEnv)
 

Variables

static SERVICE_STATUS_HANDLE status_handle
 

Function Documentation

◆ my_test_server()

static void my_test_server ( PCSTR  service_nameA,
PCWSTR  service_nameW,
void param 
)
static

Definition at line 168 of file ServiceEnv.c.

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}
static WCHAR service_nameW[100]
Definition: ServiceArgs.c:16
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
static SERVICE_STATUS ServiceStatus
Definition: browser.c:22
#define NULL
Definition: types.h:112
static const WCHAR Cleanup[]
Definition: register.c:80
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint res
Definition: glext.h:9613
#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
DWORD dwCurrentState
Definition: winsvc.h:100
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
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_SERVICE_NOT_ACTIVE
Definition: winerror.h:613
#define SERVICE_STOPPED
Definition: winsvc.h:21
#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_STOP
Definition: winsvc.h:36
#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

Referenced by START_TEST().

◆ report_service_status()

static void report_service_status ( DWORD  dwCurrentState,
DWORD  dwWin32ExitCode,
DWORD  dwWaitHint 
)
static

Definition at line 18 of file ServiceEnv.c.

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}
static void service_ok(int cnd, const char *msg,...)
Definition: ServiceArgs.c:46
static SERVICE_STATUS_HANDLE status_handle
Definition: ServiceEnv.c:15
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:997
Definition: ps.c:97
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30

Referenced by service_handler(), and service_main().

◆ service_handler()

static VOID WINAPI service_handler ( DWORD  ctrl)
static

Definition at line 55 of file ServiceEnv.c.

56{
57 switch(ctrl)
58 {
62 default:
64 }
65}
static void report_service_status(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
Definition: ServiceEnv.c:18
#define NO_ERROR
Definition: dderror.h:5
#define ctrl
Definition: input.c:1756
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40

Referenced by service_main().

◆ service_main()

static void WINAPI service_main ( DWORD  dwArgc,
LPWSTR lpszArgv 
)
static

Definition at line 68 of file ServiceEnv.c.

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}
static VOID WINAPI service_handler(DWORD ctrl)
Definition: ServiceEnv.c:55
static DWORD ServiceTag
Definition: database.c:34
Definition: bufpool.h:45
#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
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2712
unsigned long DWORD
Definition: ntddk_ex.h:95
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 DWORD
Definition: nt_native.h:44
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc)
Definition: sctrl.c:742
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
Definition: compat.h:836
void service_trace(const char *msg,...)
Definition: svchlp.c:36
uint16_t * PWSTR
Definition: typedefs.h:56
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
#define GetModuleHandle
Definition: winbase.h:3827
LPWSTR WINAPI GetEnvironmentStringsW(void)
Definition: environ.c:344
WCHAR * LPWSTR
Definition: xmlstorage.h:184

Referenced by start_service().

◆ start_service()

static BOOL start_service ( PCSTR  service_nameA,
PCWSTR  service_nameW 
)
static

Definition at line 149 of file ServiceEnv.c.

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}
static void WINAPI service_main(DWORD dwArgc, LPWSTR *lpszArgv)
Definition: ServiceEnv.c:68
BOOL WINAPI StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
Definition: sctrl.c:1134

Referenced by START_TEST().

◆ START_TEST()

START_TEST ( ServiceEnv  )

Definition at line 282 of file ServiceEnv.c.

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 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 my_test_server(PCSTR service_nameA, PCWSTR service_nameW, void *param)
Definition: ServiceEnv.c:168
#define argv
Definition: mplay32.c:18
int winetest_get_mainargs(char ***pargv)

Variable Documentation

◆ status_handle

SERVICE_STATUS_HANDLE status_handle
static

Definition at line 15 of file ServiceEnv.c.

Referenced by report_service_status(), and service_main().