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
76d4eeeb
Commit
76d4eeeb
authored
Mar 15, 2008
by
Mikołaj Zalewski
Committed by
Alexandre Julliard
Mar 29, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
services: Move ChangeServiceConfigW implementation from advapi32.dll to services.exe.
parent
a363b9a0
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
177 additions
and
45 deletions
+177
-45
service.c
dlls/advapi32/service.c
+26
-44
service.c
dlls/advapi32/tests/service.c
+19
-0
svcctl.idl
include/wine/svcctl.idl
+17
-0
rpc.c
programs/services/rpc.c
+113
-0
services.c
programs/services/services.c
+1
-1
services.h
programs/services/services.h
+1
-0
No files found.
dlls/advapi32/service.c
View file @
76d4eeeb
...
@@ -243,6 +243,18 @@ static inline LPWSTR SERV_dupmulti(LPCSTR str)
...
@@ -243,6 +243,18 @@ static inline LPWSTR SERV_dupmulti(LPCSTR str)
return
wstr
;
return
wstr
;
}
}
static
inline
DWORD
multisz_cb
(
LPCWSTR
wmultisz
)
{
const
WCHAR
*
wptr
=
wmultisz
;
if
(
wmultisz
==
NULL
)
return
0
;
while
(
*
wptr
)
wptr
+=
lstrlenW
(
wptr
)
+
1
;
return
(
wptr
-
wmultisz
+
1
)
*
sizeof
(
WCHAR
);
}
/******************************************************************************
/******************************************************************************
* RPC connection with servies.exe
* RPC connection with servies.exe
*/
*/
...
@@ -1322,7 +1334,7 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
...
@@ -1322,7 +1334,7 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
struct
sc_service
*
hsvc
=
NULL
;
struct
sc_service
*
hsvc
=
NULL
;
DWORD
new_mask
=
dwDesiredAccess
;
DWORD
new_mask
=
dwDesiredAccess
;
DWORD
len
,
err
;
DWORD
len
,
err
;
SIZE_T
depslen
=
0
,
passwdlen
;
SIZE_T
passwdlen
;
TRACE
(
"%p %s %s
\n
"
,
hSCManager
,
TRACE
(
"%p %s %s
\n
"
,
hSCManager
,
debugstr_w
(
lpServiceName
),
debugstr_w
(
lpDisplayName
));
debugstr_w
(
lpServiceName
),
debugstr_w
(
lpDisplayName
));
...
@@ -1340,16 +1352,6 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
...
@@ -1340,16 +1352,6 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
return
NULL
;
return
NULL
;
}
}
if
(
lpDependencies
)
{
const
WCHAR
*
wptr
=
lpDependencies
;
while
(
*
wptr
)
wptr
+=
strlenW
(
wptr
)
+
1
;
depslen
=
(
wptr
-
lpDependencies
+
1
)
*
sizeof
(
WCHAR
);
}
else
depslen
=
0
;
if
(
lpPassword
)
if
(
lpPassword
)
passwdlen
=
(
strlenW
(
lpPassword
)
+
1
)
*
sizeof
(
WCHAR
);
passwdlen
=
(
strlenW
(
lpPassword
)
+
1
)
*
sizeof
(
WCHAR
);
else
else
...
@@ -1370,8 +1372,9 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
...
@@ -1370,8 +1372,9 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
err
=
svcctl_CreateServiceW
(
hscm
->
hdr
.
server_handle
,
lpServiceName
,
err
=
svcctl_CreateServiceW
(
hscm
->
hdr
.
server_handle
,
lpServiceName
,
lpDisplayName
,
dwDesiredAccess
,
dwServiceType
,
dwStartType
,
dwErrorControl
,
lpDisplayName
,
dwDesiredAccess
,
dwServiceType
,
dwStartType
,
dwErrorControl
,
lpBinaryPathName
,
lpLoadOrderGroup
,
lpdwTagId
,
(
LPBYTE
)
lpDependencies
,
depslen
,
lpBinaryPathName
,
lpLoadOrderGroup
,
lpdwTagId
,
(
LPBYTE
)
lpDependencies
,
lpServiceStartName
,
(
LPBYTE
)
lpPassword
,
passwdlen
,
&
hsvc
->
hdr
.
server_handle
);
multisz_cb
(
lpDependencies
),
lpServiceStartName
,
(
LPBYTE
)
lpPassword
,
passwdlen
,
&
hsvc
->
hdr
.
server_handle
);
if
(
err
!=
ERROR_SUCCESS
)
if
(
err
!=
ERROR_SUCCESS
)
{
{
...
@@ -2299,11 +2302,9 @@ BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
...
@@ -2299,11 +2302,9 @@ BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
LPCWSTR
lpLoadOrderGroup
,
LPDWORD
lpdwTagId
,
LPCWSTR
lpDependencies
,
LPCWSTR
lpLoadOrderGroup
,
LPDWORD
lpdwTagId
,
LPCWSTR
lpDependencies
,
LPCWSTR
lpServiceStartName
,
LPCWSTR
lpPassword
,
LPCWSTR
lpDisplayName
)
LPCWSTR
lpServiceStartName
,
LPCWSTR
lpPassword
,
LPCWSTR
lpDisplayName
)
{
{
struct
reg_value
val
[
10
];
struct
sc_service
*
hsvc
;
struct
sc_service
*
hsvc
;
DWORD
r
=
ERROR_SUCCESS
;
DWORD
cb_pwd
;
HKEY
hKey
;
DWORD
err
;
int
n
=
0
;
TRACE
(
"%p %d %d %d %s %s %p %p %s %s %s
\n
"
,
TRACE
(
"%p %d %d %d %s %s %p %p %s %s %s
\n
"
,
hService
,
dwServiceType
,
dwStartType
,
dwErrorControl
,
hService
,
dwServiceType
,
dwStartType
,
dwErrorControl
,
...
@@ -2317,37 +2318,18 @@ BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
...
@@ -2317,37 +2318,18 @@ BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
SetLastError
(
ERROR_INVALID_HANDLE
);
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
return
FALSE
;
}
}
hKey
=
hsvc
->
hkey
;
if
(
dwServiceType
!=
SERVICE_NO_CHANGE
)
service_set_dword
(
&
val
[
n
++
],
szType
,
&
dwServiceType
);
if
(
dwStartType
!=
SERVICE_NO_CHANGE
)
service_set_dword
(
&
val
[
n
++
],
szStart
,
&
dwStartType
);
if
(
dwErrorControl
!=
SERVICE_NO_CHANGE
)
service_set_dword
(
&
val
[
n
++
],
szError
,
&
dwErrorControl
);
if
(
lpBinaryPathName
)
cb_pwd
=
lpPassword
?
(
strlenW
(
lpPassword
)
+
1
)
*
sizeof
(
WCHAR
)
:
0
;
service_set_string
(
&
val
[
n
++
],
szImagePath
,
lpBinaryPathName
);
if
(
lpLoadOrderGroup
)
err
=
svcctl_ChangeServiceConfigW
(
hsvc
->
hdr
.
server_handle
,
dwServiceType
,
service_set_string
(
&
val
[
n
++
],
szGroup
,
lpLoadOrderGroup
);
dwStartType
,
dwErrorControl
,
lpBinaryPathName
,
lpLoadOrderGroup
,
lpdwTagId
,
(
const
BYTE
*
)
lpDependencies
,
multisz_cb
(
lpDependencies
),
lpServiceStartName
,
(
const
BYTE
*
)
lpPassword
,
cb_pwd
,
lpDisplayName
);
/* FIXME: lpDependencies is used to create/change both DependOnService and DependOnGroup
if
(
err
!=
ERROR_SUCCESS
)
* There is no such key as what szDependencies refers to */
SetLastError
(
err
);
if
(
lpDependencies
)
service_set_multi_string
(
&
val
[
n
++
],
szDependencies
,
lpDependencies
);
if
(
lpPassword
)
FIXME
(
"ignoring password
\n
"
);
if
(
lpServiceStartName
)
service_set_string
(
&
val
[
n
++
],
szObjectName
,
lpServiceStartName
);
r
=
service_write_values
(
hsvc
->
hkey
,
val
,
n
);
return
(
r
==
ERROR_SUCCESS
)
?
TRUE
:
FALSE
;
return
err
==
ERROR_SUCCESS
;
}
}
/******************************************************************************
/******************************************************************************
...
...
dlls/advapi32/tests/service.c
View file @
76d4eeeb
...
@@ -730,6 +730,7 @@ static void test_sequence(void)
...
@@ -730,6 +730,7 @@ static void test_sequence(void)
DWORD
given
,
needed
;
DWORD
given
,
needed
;
static
const
CHAR
servicename
[]
=
"Winetest"
;
static
const
CHAR
servicename
[]
=
"Winetest"
;
static
const
CHAR
displayname
[]
=
"Winetest dummy service"
;
static
const
CHAR
displayname
[]
=
"Winetest dummy service"
;
static
const
CHAR
displayname2
[]
=
"Winetest dummy service (2)"
;
static
const
CHAR
pathname
[]
=
"we_dont_care.exe"
;
static
const
CHAR
pathname
[]
=
"we_dont_care.exe"
;
static
const
CHAR
dependencies
[]
=
"Master1
\0
Master2
\0
+MasterGroup1
\0
"
;
static
const
CHAR
dependencies
[]
=
"Master1
\0
Master2
\0
+MasterGroup1
\0
"
;
static
const
CHAR
password
[]
=
""
;
static
const
CHAR
password
[]
=
""
;
...
@@ -823,6 +824,24 @@ static void test_sequence(void)
...
@@ -823,6 +824,24 @@ static void test_sequence(void)
ok
(
!
strcmp
(
config
->
lpServiceStartName
,
localsystem
),
"Expected 'LocalSystem', got '%s'
\n
"
,
config
->
lpServiceStartName
);
ok
(
!
strcmp
(
config
->
lpServiceStartName
,
localsystem
),
"Expected 'LocalSystem', got '%s'
\n
"
,
config
->
lpServiceStartName
);
ok
(
!
strcmp
(
config
->
lpDisplayName
,
displayname
),
"Expected '%s', got '%s'
\n
"
,
displayname
,
config
->
lpDisplayName
);
ok
(
!
strcmp
(
config
->
lpDisplayName
,
displayname
),
"Expected '%s', got '%s'
\n
"
,
displayname
,
config
->
lpDisplayName
);
ok
(
ChangeServiceConfigA
(
svc_handle
,
SERVICE_NO_CHANGE
,
SERVICE_NO_CHANGE
,
SERVICE_ERROR_NORMAL
,
NULL
,
"TestGroup2"
,
NULL
,
NULL
,
NULL
,
NULL
,
displayname2
),
"ChangeServiceConfig failed (err=%d)
\n
"
,
GetLastError
());
QueryServiceConfigA
(
svc_handle
,
NULL
,
0
,
&
needed
);
config
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
config
,
needed
);
ok
(
QueryServiceConfigA
(
svc_handle
,
config
,
needed
,
&
needed
),
"QueryServiceConfig failed
\n
"
);
ok
(
config
->
lpBinaryPathName
&&
config
->
lpLoadOrderGroup
&&
config
->
lpDependencies
&&
config
->
lpServiceStartName
&&
config
->
lpDisplayName
,
"Expected all string struct members to be non-NULL
\n
"
);
ok
(
config
->
dwServiceType
==
(
SERVICE_INTERACTIVE_PROCESS
|
SERVICE_WIN32_OWN_PROCESS
),
"Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d
\n
"
,
config
->
dwServiceType
);
ok
(
config
->
dwStartType
==
SERVICE_DISABLED
,
"Expected SERVICE_DISABLED, got %d
\n
"
,
config
->
dwStartType
);
ok
(
config
->
dwErrorControl
==
SERVICE_ERROR_NORMAL
,
"Expected SERVICE_ERROR_NORMAL, got %d
\n
"
,
config
->
dwErrorControl
);
ok
(
!
strcmp
(
config
->
lpBinaryPathName
,
pathname
),
"Expected '%s', got '%s'
\n
"
,
pathname
,
config
->
lpBinaryPathName
);
ok
(
!
strcmp
(
config
->
lpLoadOrderGroup
,
"TestGroup2"
),
"Expected 'TestGroup2', got '%s'
\n
"
,
config
->
lpLoadOrderGroup
);
ok
(
config
->
dwTagId
==
0
,
"Expected 0, got %d
\n
"
,
config
->
dwTagId
);
ok
(
!
strcmp
(
config
->
lpServiceStartName
,
localsystem
),
"Expected 'LocalSystem', got '%s'
\n
"
,
config
->
lpServiceStartName
);
ok
(
!
strcmp
(
config
->
lpDisplayName
,
displayname2
),
"Expected '%s', got '%s'
\n
"
,
displayname2
,
config
->
lpDisplayName
);
SetLastError
(
0xdeadbeef
);
SetLastError
(
0xdeadbeef
);
ret
=
DeleteService
(
svc_handle
);
ret
=
DeleteService
(
svc_handle
);
ok
(
ret
,
"Expected success
\n
"
);
ok
(
ret
,
"Expected success
\n
"
);
...
...
include/wine/svcctl.idl
View file @
76d4eeeb
...
@@ -69,6 +69,23 @@ cpp_quote("#endif")
...
@@ -69,6 +69,23 @@ cpp_quote("#endif")
[
in
]
SC_RPC_HANDLE
hService
[
in
]
SC_RPC_HANDLE
hService
)
;
)
;
/*
Compatible
with
Windows
function
0
x0b
*/
DWORD
svcctl_ChangeServiceConfigW
(
[
in
]
SC_RPC_HANDLE
hService
,
[
in
]
DWORD
dwServiceType
,
[
in
]
DWORD
dwStartType
,
[
in
]
DWORD
dwErrorControl
,
[
in
,
unique
]
LPCWSTR
lpBinaryPathName
,
[
in
,
unique
]
LPCWSTR
lpLoadOrderGroupKey
,
[
in
,
out
,
unique
]
DWORD
*
lpdwTagId
,
[
in
,
unique
,
size_is
(
dwDependenciesSize
)
]
const
BYTE
*
lpDependencies
,
[
in
]
DWORD
dwDependenciesSize
,
[
in
,
unique
]
LPCWSTR
lpServiceStartName
,
[
in
,
unique
,
size_is
(
dwPasswordSize
)
]
const
BYTE
*
lpPassword
,
[
in
]
DWORD
dwPasswordSize
,
[
in
,
unique
]
LPCWSTR
lpDisplayName
)
;
/*
Compatible
with
Windows
function
0
x0c
*/
/*
Compatible
with
Windows
function
0
x0c
*/
DWORD
svcctl_CreateServiceW
(
DWORD
svcctl_CreateServiceW
(
[
in
]
SC_RPC_HANDLE
hSCManager
,
[
in
]
SC_RPC_HANDLE
hSCManager
,
...
...
programs/services/rpc.c
View file @
76d4eeeb
...
@@ -370,6 +370,119 @@ DWORD svcctl_QueryServiceConfigW(
...
@@ -370,6 +370,119 @@ DWORD svcctl_QueryServiceConfigW(
return
ERROR_SUCCESS
;
return
ERROR_SUCCESS
;
}
}
DWORD
svcctl_ChangeServiceConfigW
(
SC_RPC_HANDLE
hService
,
DWORD
dwServiceType
,
DWORD
dwStartType
,
DWORD
dwErrorControl
,
LPCWSTR
lpBinaryPathName
,
LPCWSTR
lpLoadOrderGroup
,
DWORD
*
lpdwTagId
,
const
BYTE
*
lpDependencies
,
DWORD
dwDependenciesSize
,
LPCWSTR
lpServiceStartName
,
const
BYTE
*
lpPassword
,
DWORD
dwPasswordSize
,
LPCWSTR
lpDisplayName
)
{
struct
service_entry
new_entry
;
struct
sc_service
*
service
;
DWORD
err
;
WINE_TRACE
(
"
\n
"
);
if
((
err
=
validate_service_handle
(
hService
,
SERVICE_CHANGE_CONFIG
,
&
service
))
!=
0
)
return
err
;
if
(
!
check_multisz
((
LPCWSTR
)
lpDependencies
,
dwDependenciesSize
))
return
ERROR_INVALID_PARAMETER
;
/* first check if the new configuration is correct */
lock_services
();
if
(
is_marked_for_delete
(
service
->
service_entry
))
{
unlock_services
();
return
ERROR_SERVICE_MARKED_FOR_DELETE
;
}
if
(
lpDisplayName
!=
NULL
&&
find_service_by_displayname
(
lpDisplayName
))
{
unlock_services
();
return
ERROR_DUPLICATE_SERVICE_NAME
;
}
new_entry
=
*
service
->
service_entry
;
if
(
dwServiceType
!=
SERVICE_NO_CHANGE
)
new_entry
.
config
.
dwServiceType
=
dwServiceType
;
if
(
dwStartType
!=
SERVICE_NO_CHANGE
)
new_entry
.
config
.
dwStartType
=
dwStartType
;
if
(
dwErrorControl
!=
SERVICE_NO_CHANGE
)
new_entry
.
config
.
dwErrorControl
=
dwErrorControl
;
if
(
lpBinaryPathName
!=
NULL
)
new_entry
.
config
.
lpBinaryPathName
=
(
LPWSTR
)
lpBinaryPathName
;
if
(
lpLoadOrderGroup
!=
NULL
)
new_entry
.
config
.
lpLoadOrderGroup
=
(
LPWSTR
)
lpLoadOrderGroup
;
if
(
lpdwTagId
!=
NULL
)
WINE_FIXME
(
"Changing tag id not supported
\n
"
);
if
(
lpDependencies
!=
NULL
)
WINE_FIXME
(
"Chainging dependencies not supported
\n
"
);
if
(
lpServiceStartName
!=
NULL
)
new_entry
.
config
.
lpServiceStartName
=
(
LPWSTR
)
lpServiceStartName
;
if
(
lpPassword
!=
NULL
)
WINE_FIXME
(
"Setting password not supported
\n
"
);
if
(
lpDisplayName
!=
NULL
)
new_entry
.
config
.
lpDisplayName
=
(
LPWSTR
)
lpDisplayName
;
if
(
!
validate_service_config
(
&
new_entry
))
{
WINE_ERR
(
"The configuration after the change wouldn't be valid"
);
unlock_services
();
return
ERROR_INVALID_PARAMETER
;
}
/* configuration OK. The strings needs to be duplicated */
if
(
lpBinaryPathName
!=
NULL
)
{
HeapFree
(
GetProcessHeap
(),
0
,
service
->
service_entry
->
config
.
lpBinaryPathName
);
new_entry
.
config
.
lpBinaryPathName
=
strdupW
(
lpBinaryPathName
);
}
if
(
lpLoadOrderGroup
!=
NULL
)
{
HeapFree
(
GetProcessHeap
(),
0
,
service
->
service_entry
->
config
.
lpLoadOrderGroup
);
new_entry
.
config
.
lpLoadOrderGroup
=
strdupW
(
lpLoadOrderGroup
);
}
if
(
lpServiceStartName
!=
NULL
)
{
HeapFree
(
GetProcessHeap
(),
0
,
service
->
service_entry
->
config
.
lpServiceStartName
);
new_entry
.
config
.
lpServiceStartName
=
strdupW
(
lpServiceStartName
);
}
if
(
lpDisplayName
!=
NULL
)
{
HeapFree
(
GetProcessHeap
(),
0
,
service
->
service_entry
->
config
.
lpDisplayName
);
new_entry
.
config
.
lpDisplayName
=
strdupW
(
lpDisplayName
);
}
*
service
->
service_entry
=
new_entry
;
save_service_config
(
service
->
service_entry
);
unlock_services
();
return
ERROR_SUCCESS
;
}
DWORD
svcctl_CloseServiceHandle
(
DWORD
svcctl_CloseServiceHandle
(
SC_RPC_HANDLE
*
handle
)
SC_RPC_HANDLE
*
handle
)
{
{
...
...
programs/services/services.c
View file @
76d4eeeb
...
@@ -140,7 +140,7 @@ static DWORD reg_set_string_value(HKEY hKey, LPCWSTR value_name, LPCWSTR string)
...
@@ -140,7 +140,7 @@ static DWORD reg_set_string_value(HKEY hKey, LPCWSTR value_name, LPCWSTR string)
return
RegSetValueExW
(
hKey
,
value_name
,
0
,
REG_SZ
,
(
LPBYTE
)
string
,
sizeof
(
WCHAR
)
*
(
strlenW
(
string
)
+
1
));
return
RegSetValueExW
(
hKey
,
value_name
,
0
,
REG_SZ
,
(
LPBYTE
)
string
,
sizeof
(
WCHAR
)
*
(
strlenW
(
string
)
+
1
));
}
}
static
DWORD
save_service_config
(
struct
service_entry
*
entry
)
DWORD
save_service_config
(
struct
service_entry
*
entry
)
{
{
HKEY
hServicesRootKey
;
HKEY
hServicesRootKey
;
DWORD
err
;
DWORD
err
;
...
...
programs/services/services.h
View file @
76d4eeeb
...
@@ -41,6 +41,7 @@ struct service_entry *find_service(LPCWSTR name);
...
@@ -41,6 +41,7 @@ struct service_entry *find_service(LPCWSTR name);
struct
service_entry
*
find_service_by_displayname
(
LPCWSTR
name
);
struct
service_entry
*
find_service_by_displayname
(
LPCWSTR
name
);
DWORD
add_service
(
struct
service_entry
*
entry
);
DWORD
add_service
(
struct
service_entry
*
entry
);
DWORD
remove_service
(
struct
service_entry
*
entry
);
DWORD
remove_service
(
struct
service_entry
*
entry
);
DWORD
save_service_config
(
struct
service_entry
*
entry
);
void
free_service_entry
(
struct
service_entry
*
entry
);
void
free_service_entry
(
struct
service_entry
*
entry
);
void
release_service
(
struct
service_entry
*
service
);
void
release_service
(
struct
service_entry
*
service
);
...
...
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