Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Package registry
Container registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Lorenzo Ferrillo
wine
Commits
afc4284d
Commit
afc4284d
authored
12 years ago
by
Piotr Caban
Committed by
Alexandre Julliard
12 years ago
Browse files
Options
Downloads
Patches
Plain Diff
services: Added tests for service thread termination without setting service state to stopped.
parent
522bc15b
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
programs/services/tests/service.c
+188
-31
188 additions, 31 deletions
programs/services/tests/service.c
with
188 additions
and
31 deletions
programs/services/tests/service.c
+
188
−
31
View file @
afc4284d
...
...
@@ -123,12 +123,12 @@ static void WINAPI service_main(DWORD argc, char **argv)
service_ok
(
res
,
"SetServiceStatus(SERVICE_STOPPED) failed: %u"
,
GetLastError
());
}
static
void
service_process
(
void
)
static
void
service_process
(
void
(
WINAPI
*
p_service_main
)(
DWORD
,
char
**
)
)
{
BOOL
res
;
static
const
SERVICE_TABLE_ENTRYA
servtbl
[]
=
{
{
service_name
,
service_main
},
SERVICE_TABLE_ENTRYA
servtbl
[]
=
{
{
service_name
,
p_
service_main
},
{
NULL
,
NULL
}
};
...
...
@@ -150,7 +150,66 @@ static void service_process(void)
res
=
StartServiceCtrlDispatcherA
(
servtbl
);
service_ok
(
res
,
"StartServiceCtrlDispatcher failed: %u
\n
"
,
GetLastError
());
/* Let service thread terminate */
Sleep
(
50
);
CloseHandle
(
service_stop_event
);
CloseHandle
(
pipe_handle
);
}
static
DWORD
WINAPI
no_stop_handler
(
DWORD
ctrl
,
DWORD
event_type
,
void
*
event_data
,
void
*
context
)
{
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
:
case
SERVICE_CONTROL_SHUTDOWN
:
service_event
(
"STOP"
);
status
.
dwCurrentState
=
SERVICE_STOPPED
;
status
.
dwControlsAccepted
=
0
;
SetServiceStatus
(
service_handle
,
&
status
);
SetEvent
(
service_stop_event
);
return
NO_ERROR
;
default:
status
.
dwCurrentState
=
SERVICE_RUNNING
;
SetServiceStatus
(
service_handle
,
&
status
);
return
NO_ERROR
;
}
}
static
void
WINAPI
no_stop_main
(
DWORD
argc
,
char
**
argv
)
{
SERVICE_STATUS
status
;
BOOL
res
;
service_ok
(
argc
==
1
,
"argc = %d"
,
argc
);
if
(
argc
)
service_ok
(
!
strcmp
(
argv
[
0
],
service_name
),
"argv[0] = %s, expected %s"
,
argv
[
0
],
service_name
);
service_handle
=
pRegisterServiceCtrlHandlerExA
(
service_name
,
no_stop_handler
,
NULL
);
service_ok
(
service_handle
!=
NULL
,
"RegisterServiceCtrlHandlerEx failed: %u
\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: %u"
,
GetLastError
());
service_event
(
"RUNNING"
);
}
/* Test process global variables */
...
...
@@ -160,7 +219,7 @@ static char current_event[32];
static
HANDLE
event_handle
=
INVALID_HANDLE_VALUE
;
static
CRITICAL_SECTION
event_cs
;
static
SC_HANDLE
register_service
(
void
)
static
SC_HANDLE
register_service
(
const
char
*
test_name
)
{
char
service_cmd
[
MAX_PATH
+
150
],
*
ptr
;
SC_HANDLE
service
;
...
...
@@ -175,6 +234,8 @@ static SC_HANDLE register_service(void)
strcpy
(
ptr
,
" service "
);
ptr
+=
strlen
(
ptr
);
sprintf
(
ptr
,
"%s "
,
test_name
);
ptr
+=
strlen
(
ptr
);
strcpy
(
ptr
,
service_name
);
trace
(
"service_cmd
\"
%s
\"\n
"
,
service_cmd
);
...
...
@@ -233,7 +294,7 @@ static DWORD WINAPI pipe_thread(void *arg)
trace
(
"service trace: %s
\n
"
,
ptr
+
6
);
}
else
if
(
!
strncmp
(
ptr
,
"OK:"
,
3
))
{
ok
(
1
,
"service: %s
\n
"
,
ptr
+
3
);
}
else
if
(
!
strncmp
(
ptr
,
"FAIL:"
,
3
))
{
}
else
if
(
!
strncmp
(
ptr
,
"FAIL:"
,
5
))
{
ok
(
0
,
"service: %s
\n
"
,
ptr
+
5
);
}
else
if
(
!
strncmp
(
ptr
,
"EVENT:"
,
6
))
{
trace
(
"service event: %s
\n
"
,
ptr
+
6
);
...
...
@@ -253,53 +314,147 @@ static DWORD WINAPI pipe_thread(void *arg)
return
0
;
}
static
void
test_
process
(
void
)
static
void
test_
service
(
void
)
{
SC_HANDLE
service_handle
;
SC_HANDLE
service_handle
=
register_service
(
"simple_service"
)
;
SERVICE_STATUS
status
;
HANDLE
thread
;
BOOL
res
;
sprintf
(
service_name
,
"WineTestService%d"
,
GetTickCount
());
trace
(
"service_name: %s
\n
"
,
service_name
);
sprintf
(
named_pipe_name
,
"
\\\\
.
\\
pipe
\\
%s_pipe"
,
service_name
);
pipe_handle
=
CreateNamedPipeA
(
named_pipe_name
,
PIPE_ACCESS_INBOUND
,
PIPE_TYPE_BYTE
|
PIPE_READMODE_BYTE
|
PIPE_WAIT
,
10
,
2048
,
2048
,
10000
,
NULL
);
ok
(
pipe_handle
!=
INVALID_HANDLE_VALUE
,
"CreateNamedPipe failed: %u
\n
"
,
GetLastError
());
if
(
pipe_handle
==
INVALID_HANDLE_VALUE
)
if
(
!
service_handle
)
return
;
InitializeCriticalSection
(
&
event_cs
);
event_handle
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
ok
(
event_handle
!=
INVALID_HANDLE_VALUE
,
"CreateEvent failed: %u
\n
"
,
GetLastError
());
if
(
event_handle
==
INVALID_HANDLE_VALUE
)
trace
(
"starting...
\n
"
);
res
=
StartServiceA
(
service_handle
,
0
,
NULL
);
ok
(
res
,
"StartService failed: %u
\n
"
,
GetLastError
());
if
(
!
res
)
{
DeleteService
(
service_handle
);
return
;
}
expect_event
(
"RUNNING"
);
thread
=
CreateThread
(
NULL
,
0
,
pipe_thread
,
NULL
,
0
,
NULL
);
ok
(
thread
!=
NULL
,
"CreateThread failed: %u
\n
"
,
GetLastError
());
if
(
!
thread
)
return
;
res
=
QueryServiceStatus
(
service_handle
,
&
status
);
ok
(
res
,
"QueryServiceStatus failed: %d
\n
"
,
GetLastError
());
todo_wine
ok
(
status
.
dwServiceType
==
SERVICE_WIN32_OWN_PROCESS
,
"status.dwServiceType = %x
\n
"
,
status
.
dwServiceType
);
ok
(
status
.
dwCurrentState
==
SERVICE_RUNNING
,
"status.dwCurrentState = %x
\n
"
,
status
.
dwCurrentState
);
ok
(
status
.
dwControlsAccepted
==
(
SERVICE_ACCEPT_STOP
|
SERVICE_ACCEPT_SHUTDOWN
),
"status.dwControlsAccepted = %x
\n
"
,
status
.
dwControlsAccepted
);
ok
(
status
.
dwWin32ExitCode
==
0
,
"status.dwExitCode = %d
\n
"
,
status
.
dwWin32ExitCode
);
ok
(
status
.
dwServiceSpecificExitCode
==
0
,
"status.dwServiceSpecificExitCode = %d
\n
"
,
status
.
dwServiceSpecificExitCode
);
ok
(
status
.
dwCheckPoint
==
0
,
"status.dwCheckPoint = %d
\n
"
,
status
.
dwCheckPoint
);
todo_wine
ok
(
status
.
dwWaitHint
==
0
,
"status.dwWaitHint = %d
\n
"
,
status
.
dwWaitHint
);
res
=
ControlService
(
service_handle
,
SERVICE_CONTROL_STOP
,
&
status
);
ok
(
res
,
"ControlService failed: %u
\n
"
,
GetLastError
());
expect_event
(
"STOP"
);
res
=
DeleteService
(
service_handle
);
ok
(
res
,
"DeleteService failed: %u
\n
"
,
GetLastError
());
CloseServiceHandle
(
service_handle
);
}
static
inline
void
test_no_stop
(
void
)
{
SC_HANDLE
service_handle
=
register_service
(
"no_stop"
);
SERVICE_STATUS
status
;
BOOL
res
;
service_handle
=
register_service
();
if
(
!
service_handle
)
return
;
trace
(
"starting...
\n
"
);
res
=
StartServiceA
(
service_handle
,
0
,
NULL
);
ok
(
res
,
"StartService failed: %u
\n
"
,
GetLastError
());
if
(
!
res
)
if
(
!
res
)
{
DeleteService
(
service_handle
);
return
;
}
expect_event
(
"RUNNING"
);
/* Let service thread terminate */
Sleep
(
1000
);
res
=
QueryServiceStatus
(
service_handle
,
&
status
);
ok
(
res
,
"QueryServiceStatus failed: %d
\n
"
,
GetLastError
());
todo_wine
ok
(
status
.
dwServiceType
==
SERVICE_WIN32_OWN_PROCESS
,
"status.dwServiceType = %x
\n
"
,
status
.
dwServiceType
);
ok
(
status
.
dwCurrentState
==
SERVICE_RUNNING
,
"status.dwCurrentState = %x
\n
"
,
status
.
dwCurrentState
);
ok
(
status
.
dwControlsAccepted
==
(
SERVICE_ACCEPT_STOP
|
SERVICE_ACCEPT_SHUTDOWN
),
"status.dwControlsAccepted = %x
\n
"
,
status
.
dwControlsAccepted
);
ok
(
status
.
dwWin32ExitCode
==
0
,
"status.dwExitCode = %d
\n
"
,
status
.
dwWin32ExitCode
);
ok
(
status
.
dwServiceSpecificExitCode
==
0
,
"status.dwServiceSpecificExitCode = %d
\n
"
,
status
.
dwServiceSpecificExitCode
);
ok
(
status
.
dwCheckPoint
==
0
,
"status.dwCheckPoint = %d
\n
"
,
status
.
dwCheckPoint
);
todo_wine
ok
(
status
.
dwWaitHint
==
0
,
"status.dwWaitHint = %d
\n
"
,
status
.
dwWaitHint
);
res
=
ControlService
(
service_handle
,
SERVICE_CONTROL_STOP
,
&
status
);
ok
(
res
,
"ControlService failed: %u
\n
"
,
GetLastError
());
expect_event
(
"STOP"
);
res
=
QueryServiceStatus
(
service_handle
,
&
status
);
ok
(
res
,
"QueryServiceStatus failed: %d
\n
"
,
GetLastError
());
todo_wine
ok
(
status
.
dwServiceType
==
SERVICE_WIN32_OWN_PROCESS
,
"status.dwServiceType = %x
\n
"
,
status
.
dwServiceType
);
ok
(
status
.
dwCurrentState
==
SERVICE_STOPPED
||
status
.
dwCurrentState
==
SERVICE_STOP_PENDING
,
"status.dwCurrentState = %x
\n
"
,
status
.
dwCurrentState
);
ok
(
status
.
dwControlsAccepted
==
0
,
"status.dwControlsAccepted = %x
\n
"
,
status
.
dwControlsAccepted
);
ok
(
status
.
dwWin32ExitCode
==
0
,
"status.dwExitCode = %d
\n
"
,
status
.
dwWin32ExitCode
);
ok
(
status
.
dwServiceSpecificExitCode
==
0
,
"status.dwServiceSpecificExitCode = %d
\n
"
,
status
.
dwServiceSpecificExitCode
);
ok
(
status
.
dwCheckPoint
==
0
,
"status.dwCheckPoint = %d
\n
"
,
status
.
dwCheckPoint
);
ok
(
status
.
dwWaitHint
==
0
,
"status.dwWaitHint = %d
\n
"
,
status
.
dwWaitHint
);
res
=
DeleteService
(
service_handle
);
ok
(
res
,
"DeleteService failed: %u
\n
"
,
GetLastError
());
res
=
QueryServiceStatus
(
service_handle
,
&
status
);
ok
(
res
,
"QueryServiceStatus failed: %d
\n
"
,
GetLastError
());
todo_wine
ok
(
status
.
dwServiceType
==
SERVICE_WIN32_OWN_PROCESS
,
"status.dwServiceType = %x
\n
"
,
status
.
dwServiceType
);
ok
(
status
.
dwCurrentState
==
SERVICE_STOPPED
||
status
.
dwCurrentState
==
SERVICE_STOP_PENDING
,
"status.dwCurrentState = %x
\n
"
,
status
.
dwCurrentState
);
ok
(
status
.
dwControlsAccepted
==
0
,
"status.dwControlsAccepted = %x
\n
"
,
status
.
dwControlsAccepted
);
ok
(
status
.
dwWin32ExitCode
==
0
,
"status.dwExitCode = %d
\n
"
,
status
.
dwWin32ExitCode
);
ok
(
status
.
dwServiceSpecificExitCode
==
0
,
"status.dwServiceSpecificExitCode = %d
\n
"
,
status
.
dwServiceSpecificExitCode
);
ok
(
status
.
dwCheckPoint
==
0
,
"status.dwCheckPoint = %d
\n
"
,
status
.
dwCheckPoint
);
ok
(
status
.
dwWaitHint
==
0
,
"status.dwWaitHint = %d
\n
"
,
status
.
dwWaitHint
);
CloseServiceHandle
(
service_handle
);
res
=
QueryServiceStatus
(
service_handle
,
&
status
);
ok
(
!
res
,
"QueryServiceStatus should have failed
\n
"
);
ok
(
GetLastError
()
==
ERROR_INVALID_HANDLE
,
"GetLastError = %d
\n
"
,
GetLastError
());
}
static
void
test_runner
(
void
(
*
p_run_test
)(
void
))
{
HANDLE
thread
;
sprintf
(
service_name
,
"WineTestService%d"
,
GetTickCount
());
trace
(
"service_name: %s
\n
"
,
service_name
);
sprintf
(
named_pipe_name
,
"
\\\\
.
\\
pipe
\\
%s_pipe"
,
service_name
);
pipe_handle
=
CreateNamedPipeA
(
named_pipe_name
,
PIPE_ACCESS_INBOUND
,
PIPE_TYPE_BYTE
|
PIPE_READMODE_BYTE
|
PIPE_WAIT
,
10
,
2048
,
2048
,
10000
,
NULL
);
ok
(
pipe_handle
!=
INVALID_HANDLE_VALUE
,
"CreateNamedPipe failed: %u
\n
"
,
GetLastError
());
if
(
pipe_handle
==
INVALID_HANDLE_VALUE
)
return
;
InitializeCriticalSection
(
&
event_cs
);
event_handle
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
ok
(
event_handle
!=
INVALID_HANDLE_VALUE
,
"CreateEvent failed: %u
\n
"
,
GetLastError
());
if
(
event_handle
==
INVALID_HANDLE_VALUE
)
return
;
thread
=
CreateThread
(
NULL
,
0
,
pipe_thread
,
NULL
,
0
,
NULL
);
ok
(
thread
!=
NULL
,
"CreateThread failed: %u
\n
"
,
GetLastError
());
if
(
!
thread
)
return
;
p_run_test
();
WaitForSingleObject
(
thread
,
INFINITE
);
CloseHandle
(
event_handle
);
CloseHandle
(
pipe_handle
);
}
START_TEST
(
service
)
...
...
@@ -319,15 +474,17 @@ START_TEST(service)
ok
(
scm_handle
!=
NULL
,
"OpenSCManager failed: %u
\n
"
,
GetLastError
());
if
(
argc
<
3
)
{
test_process
();
test_runner
(
test_service
);
test_runner
(
test_no_stop
);
}
else
{
strcpy
(
service_name
,
argv
[
2
]);
strcpy
(
service_name
,
argv
[
3
]);
sprintf
(
named_pipe_name
,
"
\\\\
.
\\
pipe
\\
%s_pipe"
,
service_name
);
service_process
();
if
(
!
strcmp
(
argv
[
2
],
"simple_service"
))
service_process
(
service_main
);
else
if
(
!
strcmp
(
argv
[
2
],
"no_stop"
))
service_process
(
no_stop_main
);
}
CloseHandle
(
event_handle
);
CloseHandle
(
pipe_handle
);
CloseServiceHandle
(
scm_handle
);
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment