Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
afa965a1
Commit
afa965a1
authored
Feb 25, 2015
by
Andrew Eikum
Committed by
Alexandre Julliard
Feb 26, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
advapi32: Partially implement NotifyServiceStatusChangeW.
parent
48f0f163
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
203 additions
and
1 deletion
+203
-1
advapi32.spec
dlls/advapi32/advapi32.spec
+1
-1
service.c
dlls/advapi32/service.c
+34
-0
service.c
dlls/advapi32/tests/service.c
+131
-0
winsvc.h
include/winsvc.h
+37
-0
No files found.
dlls/advapi32/advapi32.spec
View file @
afa965a1
...
...
@@ -496,7 +496,7 @@
@ stdcall NotifyChangeEventLog (long long)
# @ stub NotifyServiceStatusChange
# @ stub NotifyServiceStatusChangeA
# @ stub NotifyServiceStatusChangeW
@ stdcall NotifyServiceStatusChangeW(ptr long ptr)
@ stdcall ObjectCloseAuditAlarmA(str ptr long)
@ stdcall ObjectCloseAuditAlarmW(wstr ptr long)
# @ stub ObjectDeleteAuditAlarmA
...
...
dlls/advapi32/service.c
View file @
afa965a1
...
...
@@ -2335,3 +2335,37 @@ BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
*
lpServicesReturned
=
0
;
return
TRUE
;
}
/******************************************************************************
* NotifyServiceStatusChangeW [ADVAPI32.@]
*/
DWORD
WINAPI
NotifyServiceStatusChangeW
(
SC_HANDLE
hService
,
DWORD
dwNotifyMask
,
SERVICE_NOTIFYW
*
pNotifyBuffer
)
{
DWORD
dummy
;
BOOL
ret
;
SERVICE_STATUS_PROCESS
st
;
FIXME
(
"%p 0x%x %p - semi-stub
\n
"
,
hService
,
dwNotifyMask
,
pNotifyBuffer
);
ret
=
QueryServiceStatusEx
(
hService
,
SC_STATUS_PROCESS_INFO
,
(
void
*
)
&
st
,
sizeof
(
st
),
&
dummy
);
if
(
ret
)
{
/* dwNotifyMask is a set of bitflags in same order as SERVICE_ statuses */
if
(
dwNotifyMask
&
(
1
<<
(
st
.
dwCurrentState
-
SERVICE_STOPPED
)))
{
pNotifyBuffer
->
dwNotificationStatus
=
ERROR_SUCCESS
;
memcpy
(
&
pNotifyBuffer
->
ServiceStatus
,
&
st
,
sizeof
(
pNotifyBuffer
->
ServiceStatus
));
pNotifyBuffer
->
dwNotificationTriggered
=
1
<<
(
st
.
dwCurrentState
-
SERVICE_STOPPED
);
pNotifyBuffer
->
pszServiceNames
=
NULL
;
TRACE
(
"Queueing notification: 0x%x
\n
"
,
pNotifyBuffer
->
dwNotificationTriggered
);
QueueUserAPC
((
PAPCFUNC
)
pNotifyBuffer
->
pfnNotifyCallback
,
GetCurrentThread
(),
(
ULONG_PTR
)
pNotifyBuffer
);
}
}
/* TODO: If the service is not currently in a matching state, we should
* tell `services` to monitor it. */
return
ERROR_SUCCESS
;
}
dlls/advapi32/tests/service.c
View file @
afa965a1
...
...
@@ -50,6 +50,7 @@ static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
DWORD
,
LPDWORD
);
static
BOOL
(
WINAPI
*
pQueryServiceObjectSecurity
)(
SC_HANDLE
,
SECURITY_INFORMATION
,
PSECURITY_DESCRIPTOR
,
DWORD
,
LPDWORD
);
static
DWORD
(
WINAPI
*
pNotifyServiceStatusChangeW
)(
SC_HANDLE
,
DWORD
,
SERVICE_NOTIFYW
*
);
static
void
init_function_pointers
(
void
)
{
...
...
@@ -63,6 +64,7 @@ static void init_function_pointers(void)
pQueryServiceConfig2W
=
(
void
*
)
GetProcAddress
(
hadvapi32
,
"QueryServiceConfig2W"
);
pQueryServiceStatusEx
=
(
void
*
)
GetProcAddress
(
hadvapi32
,
"QueryServiceStatusEx"
);
pQueryServiceObjectSecurity
=
(
void
*
)
GetProcAddress
(
hadvapi32
,
"QueryServiceObjectSecurity"
);
pNotifyServiceStatusChangeW
=
(
void
*
)
GetProcAddress
(
hadvapi32
,
"NotifyServiceStatusChangeW"
);
}
static
void
test_open_scm
(
void
)
...
...
@@ -2195,6 +2197,75 @@ static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4
return
le1
;
}
struct
notify_data
{
SERVICE_NOTIFYW
notify
;
SC_HANDLE
svc
;
};
void
CALLBACK
cb_stopped
(
void
*
user
)
{
struct
notify_data
*
data
=
user
;
BOOL
br
;
ok
(
data
->
notify
.
dwNotificationStatus
==
ERROR_SUCCESS
,
"Got wrong notification status: %u
\n
"
,
data
->
notify
.
dwNotificationStatus
);
ok
(
data
->
notify
.
ServiceStatus
.
dwCurrentState
==
SERVICE_STOPPED
,
"Got wrong service state: 0x%x
\n
"
,
data
->
notify
.
ServiceStatus
.
dwCurrentState
);
ok
(
data
->
notify
.
dwNotificationTriggered
==
SERVICE_NOTIFY_STOPPED
,
"Got wrong notification triggered: 0x%x
\n
"
,
data
->
notify
.
dwNotificationTriggered
);
br
=
StartServiceA
(
data
->
svc
,
0
,
NULL
);
ok
(
br
,
"StartService failed: %u
\n
"
,
GetLastError
());
}
void
CALLBACK
cb_running
(
void
*
user
)
{
struct
notify_data
*
data
=
user
;
BOOL
br
;
SERVICE_STATUS
status
;
ok
(
data
->
notify
.
dwNotificationStatus
==
ERROR_SUCCESS
,
"Got wrong notification status: %u
\n
"
,
data
->
notify
.
dwNotificationStatus
);
ok
(
data
->
notify
.
ServiceStatus
.
dwCurrentState
==
SERVICE_RUNNING
,
"Got wrong service state: 0x%x
\n
"
,
data
->
notify
.
ServiceStatus
.
dwCurrentState
);
ok
(
data
->
notify
.
dwNotificationTriggered
==
SERVICE_NOTIFY_RUNNING
,
"Got wrong notification triggered: 0x%x
\n
"
,
data
->
notify
.
dwNotificationTriggered
);
br
=
ControlService
(
data
->
svc
,
SERVICE_CONTROL_STOP
,
&
status
);
ok
(
br
,
"ControlService failed: %u
\n
"
,
GetLastError
());
}
static
void
test_servicenotify
(
SC_HANDLE
svc
)
{
DWORD
dr
;
struct
notify_data
data
;
if
(
!
pNotifyServiceStatusChangeW
){
win_skip
(
"No NotifyServiceStatusChangeW
\n
"
);
return
;
}
memset
(
&
data
.
notify
,
0
,
sizeof
(
data
.
notify
));
data
.
notify
.
dwVersion
=
SERVICE_NOTIFY_STATUS_CHANGE
;
data
.
notify
.
pfnNotifyCallback
=
&
cb_stopped
;
data
.
notify
.
pContext
=
&
data
;
data
.
svc
=
svc
;
dr
=
pNotifyServiceStatusChangeW
(
svc
,
SERVICE_NOTIFY_STOPPED
|
SERVICE_NOTIFY_RUNNING
,
&
data
.
notify
);
ok
(
dr
==
ERROR_SUCCESS
,
"NotifyServiceStatusChangeW failed: %u
\n
"
,
dr
);
dr
=
SleepEx
(
100
,
TRUE
);
ok
(
dr
==
WAIT_IO_COMPLETION
,
"APC wasn't called
\n
"
);
data
.
notify
.
pfnNotifyCallback
=
&
cb_running
;
dr
=
pNotifyServiceStatusChangeW
(
svc
,
SERVICE_NOTIFY_STOPPED
|
SERVICE_NOTIFY_RUNNING
,
&
data
.
notify
);
ok
(
dr
==
ERROR_SUCCESS
,
"NotifyServiceStatusChangeW failed: %u
\n
"
,
dr
);
dr
=
SleepEx
(
100
,
TRUE
);
ok
(
dr
==
WAIT_IO_COMPLETION
,
"APC wasn't called
\n
"
);
}
static
void
test_start_stop
(
void
)
{
BOOL
ret
;
...
...
@@ -2267,6 +2338,13 @@ static void test_start_stop(void)
le
=
try_start_stop
(
svc_handle
,
displayname
,
is_nt4
);
ok
(
le
==
ERROR_SERVICE_REQUEST_TIMEOUT
,
"%d != ERROR_SERVICE_REQUEST_TIMEOUT
\n
"
,
le
);
/* create a real service and test notifications */
sprintf
(
cmd
,
"%s service serve"
,
selfname
);
displayname
=
"Winetest Service"
;
ret
=
ChangeServiceConfigA
(
svc_handle
,
SERVICE_NO_CHANGE
,
SERVICE_NO_CHANGE
,
SERVICE_NO_CHANGE
,
cmd
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
displayname
);
ok
(
ret
,
"ChangeServiceConfig() failed le=%u
\n
"
,
GetLastError
());
test_servicenotify
(
svc_handle
);
cleanup:
if
(
svc_handle
)
{
...
...
@@ -2370,6 +2448,57 @@ static void test_refcount(void)
CloseServiceHandle
(
scm_handle
);
}
static
DWORD
WINAPI
ctrl_handler
(
DWORD
ctl
,
DWORD
type
,
void
*
data
,
void
*
user
)
{
HANDLE
evt
=
user
;
switch
(
ctl
){
case
SERVICE_CONTROL_STOP
:
SetEvent
(
evt
);
break
;
case
SERVICE_CONTROL_INTERROGATE
:
return
NO_ERROR
;
}
return
ERROR_CALL_NOT_IMPLEMENTED
;
}
static
void
WINAPI
service_main
(
DWORD
argc
,
char
**
argv
)
{
SERVICE_STATUS_HANDLE
st_handle
;
SERVICE_STATUS
st
;
HANDLE
evt
=
CreateEventW
(
0
,
FALSE
,
FALSE
,
0
);
st_handle
=
RegisterServiceCtrlHandlerExA
(
""
,
&
ctrl_handler
,
evt
);
st
.
dwServiceType
=
SERVICE_WIN32_OWN_PROCESS
;
st
.
dwServiceSpecificExitCode
=
0
;
st
.
dwCurrentState
=
SERVICE_RUNNING
;
st
.
dwWin32ExitCode
=
NO_ERROR
;
st
.
dwWaitHint
=
0
;
st
.
dwControlsAccepted
=
SERVICE_ACCEPT_STOP
;
st
.
dwCheckPoint
=
0
;
SetServiceStatus
(
st_handle
,
&
st
);
WaitForSingleObject
(
evt
,
5000
);
st
.
dwCurrentState
=
SERVICE_STOPPED
;
SetServiceStatus
(
st_handle
,
&
st
);
}
static
void
run_service
(
void
)
{
char
empty
[]
=
{
0
};
SERVICE_TABLE_ENTRYA
table
[]
=
{
{
empty
,
&
service_main
},
{
0
,
0
}
};
StartServiceCtrlDispatcherA
(
table
);
}
START_TEST
(
service
)
{
SC_HANDLE
scm_handle
;
...
...
@@ -2380,6 +2509,8 @@ START_TEST(service)
GetFullPathNameA
(
myARGV
[
0
],
sizeof
(
selfname
),
selfname
,
NULL
);
if
(
myARGC
>=
3
)
{
if
(
strcmp
(
myARGV
[
2
],
"serve"
)
==
0
)
run_service
();
return
;
}
...
...
include/winsvc.h
View file @
afa965a1
...
...
@@ -159,6 +159,43 @@ typedef struct _SERVICE_STATUS_PROCESS
DWORD
dwServiceFlags
;
}
SERVICE_STATUS_PROCESS
,
*
LPSERVICE_STATUS_PROCESS
;
#define SERVICE_NOTIFY_STATUS_CHANGE 2
#define SERVICE_NOTIFY_STOPPED 0x1
#define SERVICE_NOTIFY_START_PENDING 0x2
#define SERVICE_NOTIFY_STOP_PENDING 0x4
#define SERVICE_NOTIFY_RUNNING 0x8
#define SERVICE_NOTIFY_CONTINUE_PENDING 0x10
#define SERVICE_NOTIFY_PAUSE_PENDING 0x20
#define SERVICE_NOTIFY_PAUSED 0x40
#define SERVICE_NOTIFY_CREATED 0x80
#define SERVICE_NOTIFY_DELETED 0x100
#define SERVICE_NOTIFY_DELETE_PENDING 0x200
typedef
void
(
CALLBACK
*
PFN_SC_NOTIFY_CALLBACK
)(
void
*
);
typedef
struct
_SERVICE_NOTIFY_2A
{
DWORD
dwVersion
;
PFN_SC_NOTIFY_CALLBACK
pfnNotifyCallback
;
void
*
pContext
;
DWORD
dwNotificationStatus
;
SERVICE_STATUS_PROCESS
ServiceStatus
;
DWORD
dwNotificationTriggered
;
char
*
pszServiceNames
;
}
SERVICE_NOTIFY_2A
,
SERVICE_NOTIFYA
;
typedef
struct
_SERVICE_NOTIFY_2W
{
DWORD
dwVersion
;
PFN_SC_NOTIFY_CALLBACK
pfnNotifyCallback
;
void
*
pContext
;
DWORD
dwNotificationStatus
;
SERVICE_STATUS_PROCESS
ServiceStatus
;
DWORD
dwNotificationTriggered
;
WCHAR
*
pszServiceNames
;
}
SERVICE_NOTIFY_2W
,
SERVICE_NOTIFYW
;
DWORD
WINAPI
NotifyServiceStatusChangeW
(
SC_HANDLE
,
DWORD
,
SERVICE_NOTIFYW
*
);
typedef
enum
_SC_STATUS_TYPE
{
SC_STATUS_PROCESS_INFO
=
0
}
SC_STATUS_TYPE
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment