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
f628cbba
Commit
f628cbba
authored
Sep 01, 2016
by
Sebastian Lackner
Committed by
Alexandre Julliard
Sep 01, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
services: Add a separate winedevice service for each kernel driver.
Signed-off-by:
Sebastian Lackner
<
sebastian@fds-team.de
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
b783f207
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
266 additions
and
70 deletions
+266
-70
svcctl.idl
include/wine/svcctl.idl
+1
-0
rpc.c
programs/services/rpc.c
+55
-3
services.c
programs/services/services.c
+158
-47
services.h
programs/services/services.h
+3
-2
device.c
programs/winedevice/device.c
+49
-18
No files found.
include/wine/svcctl.idl
View file @
f628cbba
...
...
@@ -36,6 +36,7 @@ cpp_quote("#define SVCCTL_STARTED_EVENT {'_','_','w','i','n','e','_','S','v','c'
/*
Service
startup
protocol
over
control
pipe
-
not
compatible
with
Windows
*/
cpp_quote
(
"#define SERVICE_PROTOCOL_MAGIC 0x57494e45"
)
cpp_quote
(
"#define SERVICE_CONTROL_START 0"
)
cpp_quote
(
"#define SERVICE_CONTROL_FORWARD_FLAG 0x80000000"
)
typedef
struct
service_start_info_t
{
...
...
programs/services/rpc.c
View file @
f628cbba
...
...
@@ -85,6 +85,7 @@ struct sc_lock
struct
scmdatabase
*
db
;
};
static
const
WCHAR
emptyW
[]
=
{
0
};
static
PTP_CLEANUP_GROUP
cleanup_group
;
HANDLE
exit_event
;
...
...
@@ -125,6 +126,44 @@ static void terminate_after_timeout(struct process_entry *process, DWORD timeout
release_process
(
process
);
}
static
void
CALLBACK
shutdown_callback
(
TP_CALLBACK_INSTANCE
*
instance
,
void
*
context
)
{
struct
process_entry
*
process
=
context
;
DWORD
result
;
result
=
WaitForSingleObject
(
process
->
control_mutex
,
30000
);
if
(
result
==
WAIT_OBJECT_0
)
{
process_send_control
(
process
,
FALSE
,
emptyW
,
SERVICE_CONTROL_STOP
,
NULL
,
0
,
&
result
);
ReleaseMutex
(
process
->
control_mutex
);
}
release_process
(
process
);
}
static
void
shutdown_shared_process
(
struct
process_entry
*
process
)
{
TP_CALLBACK_ENVIRON
environment
;
struct
service_entry
*
service
;
struct
scmdatabase
*
db
=
process
->
db
;
scmdatabase_lock
(
db
);
LIST_FOR_EACH_ENTRY
(
service
,
&
db
->
services
,
struct
service_entry
,
entry
)
{
if
(
service
->
process
!=
process
)
continue
;
service
->
status
.
dwCurrentState
=
SERVICE_STOP_PENDING
;
}
scmdatabase_unlock
(
db
);
memset
(
&
environment
,
0
,
sizeof
(
environment
));
environment
.
Version
=
1
;
environment
.
CleanupGroup
=
cleanup_group
;
environment
.
CleanupGroupCancelCallback
=
group_cancel_callback
;
if
(
!
TrySubmitThreadpoolCallback
(
shutdown_callback
,
grab_process
(
process
),
&
environment
))
release_process
(
process
);
}
static
void
free_service_strings
(
struct
service_entry
*
old
,
struct
service_entry
*
new
)
{
QUERY_SERVICE_CONFIGW
*
old_cfg
=
&
old
->
config
;
...
...
@@ -763,6 +802,8 @@ DWORD __cdecl svcctl_SetServiceStatus(
service
->
service_entry
->
process
=
NULL
;
if
(
!--
process
->
use_count
)
terminate_after_timeout
(
process
,
service_kill_timeout
);
if
(
service
->
service_entry
->
shared_process
&&
process
->
use_count
<=
1
)
shutdown_shared_process
(
process
);
release_process
(
process
);
}
...
...
@@ -1030,13 +1071,21 @@ static BOOL process_send_command(struct process_entry *process, const void *data
/******************************************************************************
* process_send_control
*/
BOOL
process_send_control
(
struct
process_entry
*
process
,
const
WCHAR
*
name
,
DWORD
control
,
const
BYTE
*
data
,
DWORD
data_size
,
DWORD
*
result
)
BOOL
process_send_control
(
struct
process_entry
*
process
,
BOOL
shared_process
,
const
WCHAR
*
name
,
DWORD
control
,
const
BYTE
*
data
,
DWORD
data_size
,
DWORD
*
result
)
{
service_start_info
*
ssi
;
DWORD
len
;
BOOL
r
;
if
(
shared_process
)
{
control
|=
SERVICE_CONTROL_FORWARD_FLAG
;
data
=
(
BYTE
*
)
name
;
data_size
=
(
strlenW
(
name
)
+
1
)
*
sizeof
(
WCHAR
);
name
=
emptyW
;
}
/* calculate how much space we need to send the startup info */
len
=
(
strlenW
(
name
)
+
1
)
*
sizeof
(
WCHAR
)
+
data_size
;
...
...
@@ -1086,6 +1135,7 @@ DWORD __cdecl svcctl_ControlService(
DWORD
access_required
;
struct
sc_service_handle
*
service
;
struct
process_entry
*
process
;
BOOL
shared_process
;
DWORD
result
;
WINE_TRACE
(
"(%p, %d, %p)
\n
"
,
hService
,
dwControl
,
lpServiceStatus
);
...
...
@@ -1165,6 +1215,7 @@ DWORD __cdecl svcctl_ControlService(
/* Hold a reference to the process while sending the command. */
process
=
grab_process
(
service
->
service_entry
->
process
);
shared_process
=
service
->
service_entry
->
shared_process
;
service_unlock
(
service
->
service_entry
);
if
(
!
process
)
...
...
@@ -1177,7 +1228,8 @@ DWORD __cdecl svcctl_ControlService(
return
ERROR_SERVICE_REQUEST_TIMEOUT
;
}
if
(
process_send_control
(
process
,
service
->
service_entry
->
name
,
dwControl
,
NULL
,
0
,
&
result
))
if
(
process_send_control
(
process
,
shared_process
,
service
->
service_entry
->
name
,
dwControl
,
NULL
,
0
,
&
result
))
result
=
ERROR_SUCCESS
;
if
(
lpServiceStatus
)
...
...
programs/services/services.c
View file @
f628cbba
...
...
@@ -683,35 +683,6 @@ static DWORD get_service_binary_path(const struct service_entry *service_entry,
ExpandEnvironmentStringsW
(
service_entry
->
config
.
lpBinaryPathName
,
*
path
,
size
);
if
(
service_entry
->
config
.
dwServiceType
==
SERVICE_KERNEL_DRIVER
||
service_entry
->
config
.
dwServiceType
==
SERVICE_FILE_SYSTEM_DRIVER
)
{
static
const
WCHAR
winedeviceW
[]
=
{
'\\'
,
'w'
,
'i'
,
'n'
,
'e'
,
'd'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
'.'
,
'e'
,
'x'
,
'e'
,
' '
,
0
};
WCHAR
system_dir
[
MAX_PATH
];
DWORD
type
,
len
;
GetSystemDirectoryW
(
system_dir
,
MAX_PATH
);
if
(
is_win64
)
{
if
(
!
GetBinaryTypeW
(
*
path
,
&
type
))
{
HeapFree
(
GetProcessHeap
(),
0
,
*
path
);
return
GetLastError
();
}
if
(
type
==
SCS_32BIT_BINARY
)
GetSystemWow64DirectoryW
(
system_dir
,
MAX_PATH
);
}
len
=
strlenW
(
system_dir
)
+
sizeof
(
winedeviceW
)
/
sizeof
(
WCHAR
)
+
strlenW
(
service_entry
->
name
);
HeapFree
(
GetProcessHeap
(),
0
,
*
path
);
if
(
!
(
*
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
)
)))
return
ERROR_NOT_ENOUGH_SERVER_MEMORY
;
lstrcpyW
(
*
path
,
system_dir
);
lstrcatW
(
*
path
,
winedeviceW
);
lstrcatW
(
*
path
,
service_entry
->
name
);
return
ERROR_SUCCESS
;
}
/* if service image is configured to systemdir, redirect it to wow64 systemdir */
if
(
service_entry
->
is_wow64
)
{
...
...
@@ -743,13 +714,83 @@ static DWORD get_service_binary_path(const struct service_entry *service_entry,
return
ERROR_SUCCESS
;
}
static
DWORD
service_start_process
(
struct
service_entry
*
service_entry
,
struct
process_entry
**
new_process
)
static
DWORD
get_winedevice_binary_path
(
WCHAR
**
path
,
BOOL
*
is_wow64
)
{
static
const
WCHAR
winedeviceW
[]
=
{
'\\'
,
'w'
,
'i'
,
'n'
,
'e'
,
'd'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
'.'
,
'e'
,
'x'
,
'e'
,
0
};
WCHAR
system_dir
[
MAX_PATH
];
DWORD
type
;
if
(
!
is_win64
)
*
is_wow64
=
FALSE
;
else
if
(
GetBinaryTypeW
(
*
path
,
&
type
))
*
is_wow64
=
(
type
==
SCS_32BIT_BINARY
);
else
return
GetLastError
();
GetSystemDirectoryW
(
system_dir
,
MAX_PATH
);
HeapFree
(
GetProcessHeap
(),
0
,
*
path
);
if
(
!
(
*
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlenW
(
system_dir
)
*
sizeof
(
WCHAR
)
+
sizeof
(
winedeviceW
))))
return
ERROR_NOT_ENOUGH_SERVER_MEMORY
;
strcpyW
(
*
path
,
system_dir
);
strcatW
(
*
path
,
winedeviceW
);
return
ERROR_SUCCESS
;
}
static
DWORD
add_winedevice_service
(
const
struct
service_entry
*
service
,
WCHAR
*
path
,
BOOL
is_wow64
,
struct
service_entry
**
entry
)
{
static
const
WCHAR
format
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'd'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
'%'
,
'u'
,
0
};
static
WCHAR
name
[
sizeof
(
format
)
/
sizeof
(
WCHAR
)
+
10
];
/* strlenW("4294967295") */
static
DWORD
current
=
0
;
struct
scmdatabase
*
db
=
service
->
db
;
DWORD
err
;
for
(;;)
{
sprintfW
(
name
,
format
,
++
current
);
if
(
!
scmdatabase_find_service
(
db
,
name
))
break
;
}
err
=
service_create
(
name
,
entry
);
if
(
err
!=
ERROR_SUCCESS
)
return
err
;
(
*
entry
)
->
is_wow64
=
is_wow64
;
(
*
entry
)
->
config
.
dwServiceType
=
SERVICE_WIN32_OWN_PROCESS
;
(
*
entry
)
->
config
.
dwStartType
=
SERVICE_DEMAND_START
;
(
*
entry
)
->
status
.
dwServiceType
=
(
*
entry
)
->
config
.
dwServiceType
;
if
(
!
((
*
entry
)
->
config
.
lpBinaryPathName
=
strdupW
(
path
)))
goto
error
;
if
(
!
((
*
entry
)
->
config
.
lpServiceStartName
=
strdupW
(
SZ_LOCAL_SYSTEM
)))
goto
error
;
if
(
!
((
*
entry
)
->
config
.
lpDisplayName
=
strdupW
(
name
)))
goto
error
;
if
(
service
->
config
.
lpLoadOrderGroup
&&
!
((
*
entry
)
->
config
.
lpLoadOrderGroup
=
strdupW
(
service
->
config
.
lpLoadOrderGroup
)))
goto
error
;
(
*
entry
)
->
db
=
db
;
list_add_tail
(
&
db
->
services
,
&
(
*
entry
)
->
entry
);
mark_for_delete
(
*
entry
);
return
ERROR_SUCCESS
;
error:
free_service_entry
(
*
entry
);
return
ERROR_NOT_ENOUGH_SERVER_MEMORY
;
}
static
DWORD
service_start_process
(
struct
service_entry
*
service_entry
,
struct
process_entry
**
new_process
,
BOOL
*
shared_process
)
{
struct
process_entry
*
process
;
PROCESS_INFORMATION
pi
;
STARTUPINFOW
si
;
BOOL
is_wow64
=
FALSE
;
HANDLE
token
;
LPWSTR
path
=
NULL
;
WCHAR
*
path
;
DWORD
err
;
BOOL
r
;
...
...
@@ -769,18 +810,80 @@ static DWORD service_start_process(struct service_entry *service_entry, struct p
service_entry
->
force_shutdown
=
FALSE
;
if
((
err
=
process_create
(
service_get_pipe_name
(),
&
process
)))
if
((
err
=
get_service_binary_path
(
service_entry
,
&
path
)))
{
WINE_ERR
(
"failed to create process object for %s, error = %u
\n
"
,
wine_dbgstr_w
(
service_entry
->
name
),
err
);
service_unlock
(
service_entry
);
return
err
;
}
if
((
err
=
get_service_binary_path
(
service_entry
,
&
path
)))
if
(
service_entry
->
config
.
dwServiceType
==
SERVICE_KERNEL_DRIVER
||
service_entry
->
config
.
dwServiceType
==
SERVICE_FILE_SYSTEM_DRIVER
)
{
struct
service_entry
*
winedevice_entry
;
WCHAR
*
group
;
if
((
err
=
get_winedevice_binary_path
(
&
path
,
&
is_wow64
)))
{
service_unlock
(
service_entry
);
HeapFree
(
GetProcessHeap
(),
0
,
path
);
return
err
;
}
err
=
add_winedevice_service
(
service_entry
,
path
,
is_wow64
,
&
winedevice_entry
);
HeapFree
(
GetProcessHeap
(),
0
,
path
);
if
(
err
!=
ERROR_SUCCESS
)
{
service_unlock
(
service_entry
);
return
err
;
}
group
=
strdupW
(
winedevice_entry
->
config
.
lpLoadOrderGroup
);
service_unlock
(
service_entry
);
free_process_entry
(
process
);
err
=
service_start
(
winedevice_entry
,
group
!=
NULL
,
(
const
WCHAR
**
)
&
group
);
HeapFree
(
GetProcessHeap
(),
0
,
group
);
if
(
err
!=
ERROR_SUCCESS
)
{
release_service
(
winedevice_entry
);
return
err
;
}
service_lock
(
service_entry
);
process
=
grab_process
(
winedevice_entry
->
process
);
release_service
(
winedevice_entry
);
if
(
!
process
)
{
service_unlock
(
service_entry
);
return
ERROR_SERVICE_REQUEST_TIMEOUT
;
}
service_entry
->
status
.
dwCurrentState
=
SERVICE_START_PENDING
;
service_entry
->
status
.
dwControlsAccepted
=
0
;
ResetEvent
(
service_entry
->
status_changed_event
);
service_entry
->
process
=
grab_process
(
process
);
service_entry
->
shared_process
=
*
shared_process
=
TRUE
;
process
->
use_count
++
;
service_unlock
(
service_entry
);
err
=
WaitForSingleObject
(
process
->
control_mutex
,
30000
);
if
(
err
!=
WAIT_OBJECT_0
)
{
release_process
(
process
);
return
ERROR_SERVICE_REQUEST_TIMEOUT
;
}
*
new_process
=
process
;
return
ERROR_SUCCESS
;
}
if
((
err
=
process_create
(
service_get_pipe_name
(),
&
process
)))
{
WINE_ERR
(
"failed to create process object for %s, error = %u
\n
"
,
wine_dbgstr_w
(
service_entry
->
name
),
err
);
service_unlock
(
service_entry
);
HeapFree
(
GetProcessHeap
(),
0
,
path
);
return
err
;
}
...
...
@@ -804,12 +907,12 @@ static DWORD service_start_process(struct service_entry *service_entry, struct p
scmdatabase_add_process
(
service_entry
->
db
,
process
);
service_entry
->
process
=
grab_process
(
process
);
service_entry
->
shared_process
=
*
shared_process
=
FALSE
;
process
->
use_count
++
;
service_unlock
(
service_entry
);
r
=
CreateProcessW
(
NULL
,
path
,
NULL
,
NULL
,
FALSE
,
CREATE_UNICODE_ENVIRONMENT
,
environment
,
NULL
,
&
si
,
&
pi
);
HeapFree
(
GetProcessHeap
(),
0
,
path
);
HeapFree
(
GetProcessHeap
(),
0
,
path
);
if
(
!
r
)
{
err
=
GetLastError
();
...
...
@@ -846,8 +949,8 @@ static DWORD service_wait_for_startup(struct service_entry *service, struct proc
/******************************************************************************
* process_send_start_message
*/
static
DWORD
process_send_start_message
(
struct
process_entry
*
process
,
const
WCHAR
*
name
,
const
WCHAR
**
argv
,
DWORD
argc
)
static
DWORD
process_send_start_message
(
struct
process_entry
*
process
,
BOOL
shared_process
,
const
WCHAR
*
name
,
const
WCHAR
*
*
argv
,
DWORD
argc
)
{
OVERLAPPED
overlapped
;
DWORD
i
,
len
,
result
;
...
...
@@ -896,7 +999,8 @@ static DWORD process_send_start_message(struct process_entry *process, const WCH
}
*
p
=
0
;
if
(
!
process_send_control
(
process
,
name
,
SERVICE_CONTROL_START
,
(
const
BYTE
*
)
str
,
len
,
&
result
))
if
(
!
process_send_control
(
process
,
shared_process
,
name
,
SERVICE_CONTROL_START
,
(
const
BYTE
*
)
str
,
len
,
&
result
))
result
=
ERROR_SERVICE_REQUEST_TIMEOUT
;
HeapFree
(
GetProcessHeap
(),
0
,
str
);
...
...
@@ -906,21 +1010,28 @@ static DWORD process_send_start_message(struct process_entry *process, const WCH
DWORD
service_start
(
struct
service_entry
*
service
,
DWORD
service_argc
,
LPCWSTR
*
service_argv
)
{
struct
process_entry
*
process
=
NULL
;
BOOL
shared_process
;
DWORD
err
;
err
=
service_start_process
(
service
,
&
process
);
err
=
service_start_process
(
service
,
&
process
,
&
shared_process
);
if
(
err
==
ERROR_SUCCESS
)
{
err
=
process_send_start_message
(
process
,
service
->
name
,
service_argv
,
service_argc
);
err
=
process_send_start_message
(
process
,
s
hared_process
,
s
ervice
->
name
,
service_argv
,
service_argc
);
if
(
err
==
ERROR_SUCCESS
)
err
=
service_wait_for_startup
(
service
,
process
);
if
(
err
==
ERROR_SUCCESS
)
ReleaseMutex
(
process
->
control_mutex
);
else
process_terminate
(
process
);
if
(
err
!=
ERROR_SUCCESS
)
{
service_lock
(
service
);
service
->
status
.
dwCurrentState
=
SERVICE_STOPPED
;
service
->
process
=
NULL
;
if
(
!--
process
->
use_count
)
process_terminate
(
process
);
release_process
(
process
);
service_unlock
(
service
);
}
ReleaseMutex
(
process
->
control_mutex
);
release_process
(
process
);
}
...
...
programs/services/services.h
View file @
f628cbba
...
...
@@ -59,6 +59,7 @@ struct service_entry
LPWSTR
dependOnServices
;
LPWSTR
dependOnGroups
;
struct
process_entry
*
process
;
BOOL
shared_process
;
BOOL
force_shutdown
;
BOOL
marked_for_delete
;
BOOL
is_wow64
;
...
...
@@ -95,8 +96,8 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
struct
process_entry
*
grab_process
(
struct
process_entry
*
process
);
void
release_process
(
struct
process_entry
*
process
);
BOOL
process_send_control
(
struct
process_entry
*
process
,
const
WCHAR
*
name
,
DWORD
control
,
const
BYTE
*
data
,
DWORD
data_size
,
DWORD
*
result
);
BOOL
process_send_control
(
struct
process_entry
*
process
,
BOOL
winedevice
,
const
WCHAR
*
name
,
DWORD
control
,
const
BYTE
*
data
,
DWORD
data_size
,
DWORD
*
result
);
void
process_terminate
(
struct
process_entry
*
process
);
extern
DWORD
service_pipe_timeout
;
...
...
programs/winedevice/device.c
View file @
f628cbba
...
...
@@ -43,6 +43,7 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
extern
NTSTATUS
CDECL
wine_ntoskrnl_main_loop
(
HANDLE
stop_event
);
static
const
WCHAR
winedeviceW
[]
=
{
'w'
,
'i'
,
'n'
,
'e'
,
'd'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
0
};
static
SERVICE_STATUS_HANDLE
service_handle
;
static
PTP_CLEANUP_GROUP
cleanup_group
;
static
SC_HANDLE
manager_handle
;
...
...
@@ -486,20 +487,57 @@ static void shutdown_drivers( void )
shutdown_in_progress
=
TRUE
;
}
static
DWORD
device_handler
(
DWORD
ctrl
,
const
WCHAR
*
driver_name
)
{
struct
wine_rb_entry
*
entry
;
DWORD
result
=
NO_ERROR
;
if
(
shutdown_in_progress
)
return
ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
EnterCriticalSection
(
&
drivers_cs
);
entry
=
wine_rb_get
(
&
wine_drivers
,
driver_name
);
switch
(
ctrl
)
{
case
SERVICE_CONTROL_START
:
if
(
entry
)
break
;
result
=
RtlNtStatusToDosError
(
create_driver
(
driver_name
));
break
;
case
SERVICE_CONTROL_STOP
:
if
(
!
entry
)
break
;
result
=
RtlNtStatusToDosError
(
unload_driver
(
entry
,
FALSE
));
break
;
default:
FIXME
(
"got driver ctrl %x for %s
\n
"
,
ctrl
,
wine_dbgstr_w
(
driver_name
)
);
break
;
}
LeaveCriticalSection
(
&
drivers_cs
);
return
result
;
}
static
DWORD
WINAPI
service_handler
(
DWORD
ctrl
,
DWORD
event_type
,
LPVOID
event_data
,
LPVOID
context
)
{
const
WCHAR
*
driver_name
=
context
;
const
WCHAR
*
service_group
=
context
;
if
(
ctrl
&
SERVICE_CONTROL_FORWARD_FLAG
)
{
if
(
!
event_data
)
return
ERROR_INVALID_PARAMETER
;
return
device_handler
(
ctrl
&
~
SERVICE_CONTROL_FORWARD_FLAG
,
(
const
WCHAR
*
)
event_data
);
}
switch
(
ctrl
)
{
case
SERVICE_CONTROL_STOP
:
case
SERVICE_CONTROL_SHUTDOWN
:
WINE_TRACE
(
"shutting down %s
\n
"
,
wine_dbgstr_w
(
driver_name
)
);
TRACE
(
"shutting down %s
\n
"
,
wine_dbgstr_w
(
service_group
)
);
set_service_status
(
service_handle
,
SERVICE_STOP_PENDING
,
0
);
shutdown_drivers
();
return
NO_ERROR
;
default:
WINE_FIXME
(
"got service ctrl %x for %s
\n
"
,
ctrl
,
wine_dbgstr_w
(
driver_name
)
);
FIXME
(
"got service ctrl %x for %s
\n
"
,
ctrl
,
wine_dbgstr_w
(
service_group
)
);
set_service_status
(
service_handle
,
SERVICE_RUNNING
,
SERVICE_ACCEPT_STOP
|
SERVICE_ACCEPT_SHUTDOWN
);
return
NO_ERROR
;
...
...
@@ -508,8 +546,7 @@ static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_
static
void
WINAPI
ServiceMain
(
DWORD
argc
,
LPWSTR
*
argv
)
{
const
WCHAR
*
driver_name
=
argv
[
0
];
NTSTATUS
status
;
const
WCHAR
*
service_group
=
(
argc
>=
2
)
?
argv
[
1
]
:
argv
[
0
];
if
(
!
(
stop_event
=
CreateEventW
(
NULL
,
TRUE
,
FALSE
,
NULL
)))
return
;
...
...
@@ -517,16 +554,16 @@ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
return
;
if
(
!
(
manager_handle
=
OpenSCManagerW
(
NULL
,
NULL
,
SC_MANAGER_CONNECT
)))
return
;
if
(
!
(
service_handle
=
RegisterServiceCtrlHandlerExW
(
driver_name
,
service_handler
,
(
void
*
)
driver_name
)))
if
(
!
(
service_handle
=
RegisterServiceCtrlHandlerExW
(
winedeviceW
,
service_handler
,
(
void
*
)
service_group
)))
return
;
EnterCriticalSection
(
&
drivers_cs
);
s
tatus
=
create_driver
(
driver_name
);
LeaveCriticalSection
(
&
drivers_cs
);
TRACE
(
"starting service group %s
\n
"
,
wine_dbgstr_w
(
service_group
)
);
s
et_service_status
(
service_handle
,
SERVICE_RUNNING
,
SERVICE_ACCEPT_STOP
|
SERVICE_ACCEPT_SHUTDOWN
);
if
(
status
==
STATUS_SUCCESS
)
wine_ntoskrnl_main_loop
(
stop_event
);
wine_ntoskrnl_main_loop
(
stop_event
);
TRACE
(
"service group %s stopped
\n
"
,
wine_dbgstr_w
(
service_group
)
);
set_service_status
(
service_handle
,
SERVICE_STOPPED
,
0
);
CloseServiceHandle
(
manager_handle
);
CloseThreadpoolCleanupGroup
(
cleanup_group
);
...
...
@@ -537,13 +574,7 @@ int wmain( int argc, WCHAR *argv[] )
{
SERVICE_TABLE_ENTRYW
service_table
[
2
];
if
(
!
argv
[
1
])
{
WINE_ERR
(
"missing device name, winedevice isn't supposed to be run manually
\n
"
);
return
1
;
}
service_table
[
0
].
lpServiceName
=
argv
[
1
];
service_table
[
0
].
lpServiceName
=
(
void
*
)
winedeviceW
;
service_table
[
0
].
lpServiceProc
=
ServiceMain
;
service_table
[
1
].
lpServiceName
=
NULL
;
service_table
[
1
].
lpServiceProc
=
NULL
;
...
...
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