ReactOS 0.4.15-dev-7924-g5949c20
service.c File Reference
#include <stdarg.h>
#include <windef.h>
#include <winsvc.h>
#include <stdio.h>
#include <winbase.h>
#include <winuser.h>
#include "wine/test.h"
Include dependency graph for service.c:

Go to the source code of this file.

Functions

static SERVICE_STATUS_HANDLE (WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
 
static void send_msg (const char *type, const char *msg)
 
static void service_trace (const char *msg)
 
static void service_event (const char *event)
 
static void service_ok (int cnd, const char *msg,...)
 
static void test_winstation (void)
 
static void test_create_window (void)
 
static BOOL CALLBACK monitor_enum_proc (HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
 
static void test_monitors (void)
 
static DWORD WINAPI service_handler (DWORD ctrl, DWORD event_type, void *event_data, void *context)
 
static void WINAPI service_main (DWORD argc, char **argv)
 
static void service_process (void(WINAPI *p_service_main)(DWORD, char **))
 
static DWORD WINAPI no_stop_handler (DWORD ctrl, DWORD event_type, void *event_data, void *context)
 
static void WINAPI no_stop_main (DWORD argc, char **argv)
 
static SC_HANDLE register_service (const char *test_name)
 
static void expect_event (const char *event_name)
 
static DWORD WINAPI pipe_thread (void *arg)
 
static void test_service (void)
 
static void test_no_stop (void)
 
static void test_runner (void(*p_run_test)(void))
 
 START_TEST (service)
 

Variables

static LPHANDLER_FUNCTION_EX
 
static LPVOID
 
static HANDLE pipe_handle = INVALID_HANDLE_VALUE
 
static char service_name [100]
 
static char named_pipe_name [100]
 
static SERVICE_STATUS_HANDLE service_handle
 
static HANDLE service_stop_event
 
static int monitor_count
 
static SC_HANDLE scm_handle
 
static char current_event [32]
 
static HANDLE event_handle = INVALID_HANDLE_VALUE
 
static CRITICAL_SECTION event_cs
 

Function Documentation

◆ expect_event()

static void expect_event ( const char event_name)
static

Definition at line 379 of file service.c.

380{
381 char evt[32];
382 DWORD res;
383
384 trace("waiting for %s\n", event_name);
385
387 ok(res == WAIT_OBJECT_0, "WaitForSingleObject failed: %u\n", res);
388 if(res != WAIT_OBJECT_0)
389 return;
390
392 strcpy(evt, current_event);
393 *current_event = 0;
395
396 ok(!strcmp(evt, event_name), "Unexpected event: %s, expected %s\n", evt, event_name);
397}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint res
Definition: glext.h:9613
static HANDLE event_handle
Definition: service.c:343
static char current_event[32]
Definition: service.c:342
static CRITICAL_SECTION event_cs
Definition: service.c:344
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define WAIT_OBJECT_0
Definition: winbase.h:406

Referenced by test_no_stop(), and test_service().

◆ monitor_enum_proc()

static BOOL CALLBACK monitor_enum_proc ( HMONITOR  hmon,
HDC  hdc,
LPRECT  lprc,
LPARAM  lparam 
)
static

Definition at line 132 of file service.c.

133{
134 BOOL r;
136
137 service_ok(hmon != NULL, "Unexpected hmon=%#x\n", hmon);
138
140
141 mi.cbSize = sizeof(mi);
142
143 SetLastError(0xdeadbeef);
145 service_ok(GetLastError() == ERROR_INVALID_MONITOR_HANDLE, "Unexpected GetLastError: %#x.\n", GetLastError());
146 service_ok(!r, "GetMonitorInfo with NULL HMONITOR succeeded.\n");
147
149 service_ok(r, "GetMonitorInfo failed.\n");
150
151 service_ok(mi.rcMonitor.left == 0 && mi.rcMonitor.top == 0 && mi.rcMonitor.right >= 640 && mi.rcMonitor.bottom >= 480,
152 "Unexpected monitor rcMonitor values: {%d,%d,%d,%d}\n",
154
155 service_ok(mi.rcWork.left == 0 && mi.rcWork.top == 0 && mi.rcWork.right >= 640 && mi.rcWork.bottom >= 480,
156 "Unexpected monitor rcWork values: {%d,%d,%d,%d}\n",
158
159 service_ok(!strcmp(mi.szDevice, "WinDisc") || !strcmp(mi.szDevice, "\\\\.\\DISPLAY1"),
160 "Unexpected szDevice received: %s\n", mi.szDevice);
161
162 service_ok(mi.dwFlags == MONITORINFOF_PRIMARY, "Unexpected secondary monitor info.\n");
163
164 return TRUE;
165}
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define SetLastError(x)
Definition: compat.h:752
unsigned int BOOL
Definition: ntddk_ex.h:94
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static HANDLE hmon
Definition: localmon.c:41
static void service_ok(int cnd, const char *msg,...)
Definition: service.c:59
static int monitor_count
Definition: service.c:38
RECT rcMonitor
Definition: winuser.h:3785
DWORD dwFlags
Definition: winuser.h:3787
DWORD cbSize
Definition: winuser.h:3784
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
static MONITORINFO mi
Definition: win.c:7338
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_INVALID_MONITOR_HANDLE
Definition: winerror.h:942
BOOL WINAPI GetMonitorInfoA(_In_ HMONITOR, _Inout_ LPMONITORINFO)

Referenced by test_monitors().

◆ no_stop_handler()

static DWORD WINAPI no_stop_handler ( DWORD  ctrl,
DWORD  event_type,
void event_data,
void context 
)
static

Definition at line 285 of file service.c.

286{
288
289 status.dwServiceType = SERVICE_WIN32;
290 status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
291 status.dwWin32ExitCode = 0;
292 status.dwServiceSpecificExitCode = 0;
293 status.dwCheckPoint = 0;
294 status.dwWaitHint = 0;
295
296 switch(ctrl)
297 {
300 service_event("STOP");
301 status.dwCurrentState = SERVICE_STOPPED;
302 status.dwControlsAccepted = 0;
305 return NO_ERROR;
306 default:
307 status.dwCurrentState = SERVICE_RUNNING;
309 return NO_ERROR;
310 }
311}
#define NO_ERROR
Definition: dderror.h:5
static HANDLE service_stop_event
Definition: service.c:36
static SERVICE_STATUS_HANDLE service_handle
Definition: service.c:33
static void service_event(const char *event)
Definition: service.c:54
#define ctrl
Definition: input.c:1756
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:997
Definition: ps.c:97
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define SERVICE_WIN32
Definition: cmtypes.h:964

Referenced by no_stop_main().

◆ no_stop_main()

static void WINAPI no_stop_main ( DWORD  argc,
char **  argv 
)
static

Definition at line 313 of file service.c.

314{
316 BOOL res;
317
318 service_ok(argc == 1, "argc = %u, expected 1\n", argc);
319 service_ok(!strcmp(argv[0], service_name), "argv[0] = '%s', expected '%s'\n", argv[0], service_name);
320
321 service_handle = pRegisterServiceCtrlHandlerExA(service_name, no_stop_handler, NULL);
322 service_ok(service_handle != NULL, "RegisterServiceCtrlHandlerEx failed: %u\n", GetLastError());
323 if(!service_handle)
324 return;
325
326 status.dwServiceType = SERVICE_WIN32;
327 status.dwCurrentState = SERVICE_RUNNING;
329 status.dwWin32ExitCode = 0;
330 status.dwServiceSpecificExitCode = 0;
331 status.dwCheckPoint = 0;
332 status.dwWaitHint = 10000;
334 service_ok(res, "SetServiceStatus(SERVICE_RUNNING) failed: %u\n", GetLastError());
335
336 service_event("RUNNING");
337}
static char service_name[100]
static int argc
Definition: ServiceArgs.c:12
static DWORD WINAPI no_stop_handler(DWORD ctrl, DWORD event_type, void *event_data, void *context)
Definition: service.c:285
#define argv
Definition: mplay32.c:18
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30

Referenced by START_TEST().

◆ pipe_thread()

static DWORD WINAPI pipe_thread ( void arg)
static

Definition at line 399 of file service.c.

400{
401 char buf[512], *ptr;
402 DWORD read;
403 BOOL res;
404
406 ok(res || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe failed: %u\n", GetLastError());
407
408 while(1) {
409 res = ReadFile(pipe_handle, buf, sizeof(buf), &read, NULL);
410 if(!res) {
412 "ReadFile failed: %u\n", GetLastError());
413 break;
414 }
415
416 for(ptr = buf; ptr < buf+read; ptr += strlen(ptr)+1) {
417 if(!strncmp(ptr, "TRACE:", 6)) {
418 trace("service trace: %s", ptr+6);
419 }else if(!strncmp(ptr, "OK:", 3)) {
420 ok(1, "service: %s", ptr+3);
421 }else if(!strncmp(ptr, "FAIL:", 5)) {
422 ok(0, "service: %s", ptr+5);
423 }else if(!strncmp(ptr, "EVENT:", 6)) {
424 trace("service event: %s\n", ptr+6);
426 ok(!current_event[0], "event %s still queued\n", current_event);
430 }else {
431 ok(0, "malformed service message: %s\n", ptr);
432 }
433 }
434 }
435
437 trace("pipe disconnected\n");
438 return 0;
439}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define read
Definition: acwin.h:96
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static PVOID ptr
Definition: dispmode.c:27
static HANDLE pipe_handle
Definition: service.c:31
BOOL WINAPI ConnectNamedPipe(IN HANDLE hNamedPipe, IN LPOVERLAPPED lpOverlapped)
Definition: npipe.c:701
BOOL WINAPI DisconnectNamedPipe(HANDLE hNamedPipe)
Definition: npipe.c:961
#define ERROR_BROKEN_PIPE
Definition: winerror.h:183
#define ERROR_PIPE_CONNECTED
Definition: winerror.h:352

Referenced by test_runner().

◆ register_service()

static SC_HANDLE register_service ( const char test_name)
static

Definition at line 346 of file service.c.

347{
348 char service_cmd[MAX_PATH+150], *ptr;
349 SC_HANDLE service;
350
351 ptr = service_cmd + GetModuleFileNameA(NULL, service_cmd, MAX_PATH);
352
353 /* If the file doesn't exist, assume we're using built-in exe and append .so to the path */
354 if(GetFileAttributesA(service_cmd) == INVALID_FILE_ATTRIBUTES) {
355 strcpy(ptr, ".so");
356 ptr += 3;
357 }
358
359 strcpy(ptr, " service ");
360 ptr += strlen(ptr);
361 sprintf(ptr, "%s ", test_name);
362 ptr += strlen(ptr);
364
365 trace("service_cmd \"%s\"\n", service_cmd);
366
369 service_cmd, NULL, NULL, NULL, NULL, NULL);
370 if(!service && GetLastError() == ERROR_ACCESS_DENIED) {
371 skip("Not enough access right to create service\n");
372 return NULL;
373 }
374
375 ok(service != NULL, "CreateService failed: %u\n", GetLastError());
376 return service;
377}
static SC_HANDLE scm_handle
Definition: ServiceArgs.c:20
#define skip(...)
Definition: atltest.h:64
#define MAX_PATH
Definition: compat.h:34
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:636
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static const char * test_name
Definition: run.c:177
#define GENERIC_ALL
Definition: nt_native.h:92
SC_HANDLE WINAPI CreateServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, LPCSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, LPCSTR lpServiceStartName, LPCSTR lpPassword)
Definition: scm.c:680
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define SERVICE_DEMAND_START
Definition: cmtypes.h:978
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:962
#define SERVICE_ERROR_IGNORE
Definition: cmtypes.h:981

◆ send_msg()

static void send_msg ( const char type,
const char msg 
)
static

Definition at line 40 of file service.c.

41{
42 DWORD written = 0;
43 char buf[512];
44
45 sprintf(buf, "%s:%s", type, msg);
46 WriteFile(pipe_handle, buf, strlen(buf)+1, &written, NULL);
47}
#define msg(x)
Definition: auth_time.c:54
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545

Referenced by service_event(), service_ok(), and service_trace().

◆ service_event()

static void service_event ( const char event)
inlinestatic

Definition at line 54 of file service.c.

55{
56 send_msg("EVENT", event);
57}
struct _cl_event * event
Definition: glext.h:7739
static void send_msg(const char *type, const char *msg)
Definition: service.c:40

Referenced by no_stop_handler(), no_stop_main(), service_handler(), and service_main().

◆ service_handler()

static DWORD WINAPI service_handler ( DWORD  ctrl,
DWORD  event_type,
void event_data,
void context 
)
static

Definition at line 177 of file service.c.

178{
180
181 status.dwServiceType = SERVICE_WIN32;
182 status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
183 status.dwWin32ExitCode = 0;
184 status.dwServiceSpecificExitCode = 0;
185 status.dwCheckPoint = 0;
186 status.dwWaitHint = 0;
187
188 switch(ctrl)
189 {
192 service_event("STOP");
193 status.dwCurrentState = SERVICE_STOP_PENDING;
194 status.dwControlsAccepted = 0;
197 return NO_ERROR;
198 case 128:
202 service_event("CUSTOM");
203 return 0xdeadbeef;
204 default:
205 status.dwCurrentState = SERVICE_RUNNING;
207 return NO_ERROR;
208 }
209}
static void test_monitors(void)
Definition: service.c:168
static void test_create_window(void)
Definition: service.c:89
static void test_winstation(void)
Definition: service.c:71
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23

Referenced by service_main().

◆ service_main()

static void WINAPI service_main ( DWORD  argc,
char **  argv 
)
static

Definition at line 211 of file service.c.

212{
214 char buf[64];
215 BOOL res;
216
217 service_ok(argc == 3, "argc = %u, expected 3\n", argc);
218 service_ok(!strcmp(argv[0], service_name), "argv[0] = '%s', expected '%s'\n", argv[0], service_name);
219 service_ok(!strcmp(argv[1], "param1"), "argv[1] = '%s', expected 'param1'\n", argv[1]);
220 service_ok(!strcmp(argv[2], "param2"), "argv[2] = '%s', expected 'param2'\n", argv[2]);
221
222 buf[0] = 0;
223 GetEnvironmentVariableA("PATHEXT", buf, sizeof(buf));
224 service_ok(buf[0], "did not find PATHEXT environment variable\n");
225
226 service_handle = pRegisterServiceCtrlHandlerExA(service_name, service_handler, NULL);
227 service_ok(service_handle != NULL, "RegisterServiceCtrlHandlerEx failed: %u\n", GetLastError());
228 if(!service_handle)
229 return;
230
231 status.dwServiceType = SERVICE_WIN32;
232 status.dwCurrentState = SERVICE_RUNNING;
234 status.dwWin32ExitCode = 0;
235 status.dwServiceSpecificExitCode = 0;
236 status.dwCheckPoint = 0;
237 status.dwWaitHint = 10000;
239 service_ok(res, "SetServiceStatus(SERVICE_RUNNING) failed: %u\n", GetLastError());
240
241 service_event("RUNNING");
242
244
245 status.dwCurrentState = SERVICE_STOPPED;
246 status.dwControlsAccepted = 0;
248 service_ok(res, "SetServiceStatus(SERVICE_STOPPED) failed: %u\n", GetLastError());
249}
#define GetEnvironmentVariableA(x, y, z)
Definition: compat.h:754
#define INFINITE
Definition: serial.h:102
static DWORD WINAPI service_handler(DWORD ctrl, DWORD event_type, void *event_data, void *context)
Definition: service.c:177

◆ service_ok()

static void service_ok ( int  cnd,
const char msg,
  ... 
)
static

Definition at line 59 of file service.c.

60{
62 char buf[512];
63
67
68 send_msg(cnd ? "OK" : "FAIL", buf);
69}
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
int __cdecl vsprintf(char *_Dest, const char *_Format, va_list _Args)
Definition: sprintf.c:733
static __ms_va_list valist
Definition: printf.c:66

Referenced by monitor_enum_proc(), no_stop_main(), service_main(), service_process(), test_create_window(), test_monitors(), and test_winstation().

◆ service_process()

static void service_process ( void(WINAPI *p_service_main)(DWORD, char **)  )
static

Definition at line 251 of file service.c.

252{
253 BOOL res;
254
255 SERVICE_TABLE_ENTRYA servtbl[] = {
256 {service_name, p_service_main},
257 {NULL, NULL}
258 };
259
261 if(!res)
262 return;
263
266 return;
267
268 service_trace("Starting...\n");
269
271 service_ok(service_stop_event != NULL, "Could not create event: %u\n", GetLastError());
273 return;
274
276 service_ok(res, "StartServiceCtrlDispatcher failed: %u\n", GetLastError());
277
278 /* Let service thread terminate */
279 Sleep(50);
280
283}
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static void service_trace(const char *msg)
Definition: service.c:49
static char named_pipe_name[100]
Definition: service.c:32
BOOL WINAPI WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut)
Definition: npipe.c:433
#define GENERIC_WRITE
Definition: nt_native.h:90
BOOL WINAPI StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
Definition: sctrl.c:1035
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637
#define NMPWAIT_USE_DEFAULT_WAIT
Definition: winbase.h:134

Referenced by START_TEST().

◆ SERVICE_STATUS_HANDLE()

static SERVICE_STATUS_HANDLE ( WINAPI pRegisterServiceCtrlHandlerExA)
static

◆ service_trace()

static void service_trace ( const char msg)
inlinestatic

Definition at line 49 of file service.c.

50{
51 send_msg("TRACE", msg);
52}

Referenced by service_process().

◆ START_TEST()

START_TEST ( service  )

Definition at line 615 of file service.c.

616{
617 char **argv;
618 int argc;
619
621
622 pRegisterServiceCtrlHandlerExA = (void*)GetProcAddress(GetModuleHandleA("advapi32.dll"), "RegisterServiceCtrlHandlerExA");
623 if(!pRegisterServiceCtrlHandlerExA) {
624 win_skip("RegisterServiceCtrlHandlerExA not available, skipping tests\n");
625 return;
626 }
627
629 ok(scm_handle != NULL || GetLastError() == ERROR_ACCESS_DENIED, "OpenSCManager failed: %u\n", GetLastError());
630 if(!scm_handle) {
631 skip("OpenSCManager failed, skipping tests\n");
632 return;
633 }
634
636
637 if(argc < 3) {
640 }else {
642 sprintf(named_pipe_name, "\\\\.\\pipe\\%s_pipe", service_name);
643
644 if(!strcmp(argv[2], "simple_service"))
646 else if(!strcmp(argv[2], "no_stop"))
648 }
649
651}
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
Definition: service.c:132
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
static void service_process(void(WINAPI *p_service_main)(DWORD, char **))
Definition: service.c:251
static void test_runner(void(*p_run_test)(void))
Definition: service.c:583
static void WINAPI no_stop_main(DWORD argc, char **argv)
Definition: service.c:313
static void test_no_stop(void)
Definition: service.c:494
static void test_service(void)
Definition: service.c:441
SC_HANDLE WINAPI OpenSCManagerA(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess)
Definition: scm.c:2024
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:580
#define win_skip
Definition: test.h:160
int winetest_get_mainargs(char ***pargv)
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751

◆ test_create_window()

static void test_create_window ( void  )
static

Definition at line 89 of file service.c.

90{
92 ATOM class;
93 HWND hwnd;
94 BOOL r;
95
96 static WNDCLASSEXA wndclass = {
97 sizeof(WNDCLASSEXA),
98 0,
100 0, 0, NULL, NULL, NULL, NULL, NULL,
101 "service_test",
102 NULL
103 };
104
106 service_ok(IsWindow(hwnd), "GetDesktopWindow returned invalid window %p\n", hwnd);
107
108 class = RegisterClassExA(&wndclass);
109 service_ok(class, "RegisterClassFailed\n");
110
111 hwnd = CreateWindowA("service_test", "service_test",
113 515, 530, NULL, NULL, NULL, NULL);
114 service_ok(hwnd != NULL, "CreateWindow failed: %u\n", GetLastError());
115
117 service_ok(!(style & WS_VISIBLE), "style = %x, expected invisible\n", style);
118
120 service_ok(!r, "ShowWindow returned %x\n", r);
121
123 service_ok(style & WS_VISIBLE, "style = %x, expected visible\n", style);
124
126 service_ok(r, "ShowWindow returned %x\n", r);
127
129 service_ok(r, "DestroyWindow failed: %08x\n", GetLastError());
130}
Arabic default style
Definition: afstyles.h:94
WORD ATOM
Definition: dimm.idl:113
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
#define WS_VISIBLE
Definition: pedump.c:620
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
BOOL WINAPI IsWindow(_In_opt_ HWND)
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4315
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:656
ATOM WINAPI RegisterClassExA(_In_ CONST WNDCLASSEXA *)
#define CW_USEDEFAULT
Definition: winuser.h:225
struct _WNDCLASSEXA WNDCLASSEXA
#define SW_SHOW
Definition: winuser.h:775
#define GWL_STYLE
Definition: winuser.h:852
BOOL WINAPI DestroyWindow(_In_ HWND)

Referenced by service_handler().

◆ test_monitors()

static void test_monitors ( void  )
static

Definition at line 168 of file service.c.

169{
170 BOOL r;
171
173 service_ok(r, "EnumDisplayMonitors failed.\n");
174 service_ok(monitor_count == 1, "Callback got called less or more than once. %d\n", monitor_count);
175}
static BOOL CALLBACK monitor_enum_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
Definition: service.c:132
BOOL WINAPI EnumDisplayMonitors(_In_opt_ HDC, _In_opt_ LPCRECT, _In_ MONITORENUMPROC, _In_ LPARAM)

Referenced by service_handler().

◆ test_no_stop()

static void test_no_stop ( void  )
inlinestatic

Definition at line 494 of file service.c.

495{
496 SC_HANDLE service_handle = register_service("no_stop");
499 DWORD bytes;
500 BOOL res;
501
502 if(!service_handle)
503 return;
504
505 trace("starting...\n");
507 ok(res, "StartService failed: %u\n", GetLastError());
508 if(!res) {
511 return;
512 }
513 expect_event("RUNNING");
514
515 /* Let service thread terminate */
516 Sleep(1000);
517
519 ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
520 todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
521 ok(status.dwCurrentState == SERVICE_RUNNING, "status.dwCurrentState = %x\n", status.dwCurrentState);
522 ok(status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN),
523 "status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
524 ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
525 ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
526 status.dwServiceSpecificExitCode);
527 ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
528 todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
529
530 res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
531 ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
532 ok(status2.dwCurrentState == SERVICE_RUNNING, "status2.dwCurrentState = %x\n", status2.dwCurrentState);
533 ok(status2.dwProcessId != 0, "status2.dwProcessId = %d\n", status2.dwProcessId);
534
536 ok(res, "ControlService failed: %u\n", GetLastError());
537 expect_event("STOP");
538
540 ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
541 todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
542 ok(status.dwCurrentState==SERVICE_STOPPED || status.dwCurrentState==SERVICE_STOP_PENDING,
543 "status.dwCurrentState = %x\n", status.dwCurrentState);
544 ok(status.dwControlsAccepted == 0, "status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
545 ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
546 ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
547 status.dwServiceSpecificExitCode);
548 ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
549 ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
550
551 res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
552 ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
553 ok(status2.dwProcessId == 0 || broken(status2.dwProcessId != 0),
554 "status2.dwProcessId = %d\n", status2.dwProcessId);
555
557 ok(res, "DeleteService failed: %u\n", GetLastError());
558
560 ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
561 todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
562 ok(status.dwCurrentState==SERVICE_STOPPED || status.dwCurrentState==SERVICE_STOP_PENDING,
563 "status.dwCurrentState = %x\n", status.dwCurrentState);
564 ok(status.dwControlsAccepted == 0, "status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
565 ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
566 ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
567 status.dwServiceSpecificExitCode);
568 ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
569 ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
570
571 res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
572 ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
573 ok(status2.dwProcessId == 0 || broken(status2.dwProcessId != 0),
574 "status2.dwProcessId = %d\n", status2.dwProcessId);
575
577
579 ok(!res, "QueryServiceStatus should have failed\n");
580 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError = %d\n", GetLastError());
581}
#define broken(x)
Definition: _sntprintf.h:21
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
#define todo_wine
Definition: custom.c:79
static void expect_event(const char *event_name)
Definition: service.c:379
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2845
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:921
BOOL WINAPI StartServiceA(SC_HANDLE hService, DWORD dwNumServiceArgs, LPCSTR *lpServiceArgVectors)
Definition: scm.c:2942
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:622
BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded)
Definition: scm.c:2887
#define register_service
Definition: svchlp.h:69
@ SC_STATUS_PROCESS_INFO
Definition: winsvc.h:119
unsigned char BYTE
Definition: xxhash.c:193

Referenced by START_TEST().

◆ test_runner()

static void test_runner ( void(*)(void p_run_test)
static

Definition at line 583 of file service.c.

584{
586
587 sprintf(service_name, "WineTestService%d", GetTickCount());
588 trace("service_name: %s\n", service_name);
589 sprintf(named_pipe_name, "\\\\.\\pipe\\%s_pipe", service_name);
590
592 PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, 10, 2048, 2048, 10000, NULL);
593 ok(pipe_handle != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError());
595 return;
596
598 ok(event_handle != INVALID_HANDLE_VALUE, "CreateEvent failed: %u\n", GetLastError());
600 return;
601
603 ok(thread != NULL, "CreateThread failed: %u\n", GetLastError());
604 if(!thread)
605 return;
606
607 p_run_test();
608
613}
static HANDLE thread
Definition: service.c:33
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
static DWORD WINAPI pipe_thread(void *arg)
Definition: service.c:399
HANDLE WINAPI CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:220
#define PIPE_ACCESS_INBOUND
Definition: winbase.h:165
#define PIPE_WAIT
Definition: winbase.h:171
#define PIPE_READMODE_MESSAGE
Definition: winbase.h:170
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:168

Referenced by START_TEST().

◆ test_service()

static void test_service ( void  )
static

Definition at line 441 of file service.c.

442{
443 static const char *argv[2] = {"param1", "param2"};
444 SC_HANDLE service_handle = register_service("simple_service");
447 DWORD bytes;
448 BOOL res;
449
450 if(!service_handle)
451 return;
452
453 trace("starting...\n");
455 ok(res, "StartService failed: %u\n", GetLastError());
456 if(!res) {
459 return;
460 }
461 expect_event("RUNNING");
462
464 ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
465 todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
466 ok(status.dwCurrentState == SERVICE_RUNNING, "status.dwCurrentState = %x\n", status.dwCurrentState);
467 ok(status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN),
468 "status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
469 ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
470 ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
471 status.dwServiceSpecificExitCode);
472 ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
473 todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
474
475 res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
476 ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
477 ok(status2.dwCurrentState == SERVICE_RUNNING, "status2.dwCurrentState = %x\n", status2.dwCurrentState);
478 ok(status2.dwProcessId != 0, "status2.dwProcessId = %d\n", status2.dwProcessId);
479
481 ok(res, "ControlService failed: %u\n", GetLastError());
482 expect_event("CUSTOM");
483
485 ok(res, "ControlService failed: %u\n", GetLastError());
486 expect_event("STOP");
487
489 ok(res, "DeleteService failed: %u\n", GetLastError());
490
492}

Referenced by server_end_to_end_callback(), START_TEST(), test_end_to_end_client(), and test_end_to_end_server().

◆ test_winstation()

static void test_winstation ( void  )
static

Definition at line 71 of file service.c.

72{
73 HWINSTA winstation;
75 BOOL r;
76
77 winstation = GetProcessWindowStation();
78 service_ok(winstation != NULL, "winstation = NULL\n");
79
80 r = GetUserObjectInformationA(winstation, UOI_FLAGS, &flags, sizeof(flags), NULL);
81 service_ok(r, "GetUserObjectInformation(UOI_NAME) failed: %u\n", GetLastError());
82 service_ok(!(flags.dwFlags & WSF_VISIBLE), "winstation has flags %x\n", flags.dwFlags);
83}
GLbitfield flags
Definition: glext.h:7161
HWINSTA WINAPI GetProcessWindowStation(void)
Definition: ntwrapper.h:124
#define WSF_VISIBLE
Definition: winuser.h:2452
BOOL WINAPI GetUserObjectInformationA(_In_ HANDLE hObj, _In_ int nIndex, _Out_writes_bytes_opt_(nLength) PVOID pvInfo, _In_ DWORD nLength, _Out_opt_ LPDWORD lpnLengthNeeded)
#define UOI_FLAGS
Definition: winuser.h:1083

Referenced by service_handler().

Variable Documentation

◆ current_event

char current_event[32]
static

Definition at line 342 of file service.c.

Referenced by expect_event(), and pipe_thread().

◆ event_cs

CRITICAL_SECTION event_cs
static

Definition at line 344 of file service.c.

Referenced by expect_event(), pipe_thread(), and START_TEST().

◆ event_handle

HANDLE event_handle = INVALID_HANDLE_VALUE
static

Definition at line 343 of file service.c.

Referenced by expect_event(), pipe_thread(), and test_runner().

◆ LPHANDLER_FUNCTION_EX

LPHANDLER_FUNCTION_EX

Definition at line 29 of file service.c.

◆ LPVOID

Definition at line 29 of file service.c.

◆ monitor_count

int monitor_count
static

Definition at line 38 of file service.c.

Referenced by monitor_enum_proc(), and test_monitors().

◆ named_pipe_name

char named_pipe_name[100]
static

Definition at line 32 of file service.c.

Referenced by service_process(), START_TEST(), and test_runner().

◆ pipe_handle

HANDLE pipe_handle = INVALID_HANDLE_VALUE
static

Definition at line 31 of file service.c.

Referenced by pipe_thread(), send_msg(), service_process(), and test_runner().

◆ scm_handle

SC_HANDLE scm_handle
static

Definition at line 340 of file service.c.

◆ service_handle

SERVICE_STATUS_HANDLE service_handle
static

◆ service_name

char service_name[100]
static

Definition at line 32 of file service.c.

◆ service_stop_event

HANDLE service_stop_event
static

Definition at line 36 of file service.c.

Referenced by no_stop_handler(), service_handler(), service_main(), and service_process().