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
7135ac76
Commit
7135ac76
authored
Oct 29, 2010
by
Hans Leidekker
Committed by
Alexandre Julliard
Oct 29, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
advapi32: Implement EnumServicesStatusExA/W.
parent
27bf4c37
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
231 additions
and
60 deletions
+231
-60
service.c
dlls/advapi32/service.c
+111
-17
service.c
dlls/advapi32/tests/service.c
+5
-43
svcctl.idl
include/wine/svcctl.idl
+11
-0
rpc.c
programs/services/rpc.c
+104
-0
No files found.
dlls/advapi32/service.c
View file @
7135ac76
...
...
@@ -1558,31 +1558,125 @@ EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_ST
* EnumServicesStatusExA [ADVAPI32.@]
*/
BOOL
WINAPI
EnumServicesStatusExA
(
SC_HANDLE
hSCManager
,
SC_ENUM_TYPE
InfoLevel
,
DWORD
dwServiceType
,
DWORD
dwServiceState
,
LPBYTE
lpServices
,
DWORD
cbBufSize
,
LPDWORD
pcbBytesNeeded
,
LPDWORD
lpServicesReturned
,
LPDWORD
lpResumeHandle
,
LPCSTR
pszGroupName
)
{
FIXME
(
"%p level=%d type=%x state=%x %p %x %p %p %p %s
\n
"
,
hSCManager
,
InfoLevel
,
dwServiceType
,
dwServiceState
,
lpServices
,
cbBufSize
,
pcbBytesNeeded
,
lpServicesReturned
,
lpResumeHandle
,
debugstr_a
(
pszGroupName
));
if
(
lpServicesReturned
)
*
lpServicesReturned
=
0
;
SetLastError
(
ERROR_ACCESS_DENIED
);
EnumServicesStatusExA
(
SC_HANDLE
hmngr
,
SC_ENUM_TYPE
level
,
DWORD
type
,
DWORD
state
,
LPBYTE
buffer
,
DWORD
size
,
LPDWORD
needed
,
LPDWORD
returned
,
LPDWORD
resume_handle
,
LPCSTR
group
)
{
BOOL
ret
;
unsigned
int
i
;
ENUM_SERVICE_STATUS_PROCESSA
*
services
=
(
ENUM_SERVICE_STATUS_PROCESSA
*
)
buffer
;
ENUM_SERVICE_STATUS_PROCESSW
*
servicesW
=
NULL
;
WCHAR
*
groupW
=
NULL
;
DWORD
sz
,
n
;
char
*
p
;
TRACE
(
"%p %u 0x%x 0x%x %p %u %p %p %p %s
\n
"
,
hmngr
,
level
,
type
,
state
,
buffer
,
size
,
needed
,
returned
,
resume_handle
,
debugstr_a
(
group
));
if
(
size
&&
!
(
servicesW
=
HeapAlloc
(
GetProcessHeap
(),
0
,
2
*
size
)))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
if
(
group
)
{
int
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
group
,
-
1
,
NULL
,
0
);
if
(
!
(
groupW
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
)
)))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
HeapFree
(
GetProcessHeap
(),
0
,
servicesW
);
return
FALSE
;
}
MultiByteToWideChar
(
CP_ACP
,
0
,
group
,
-
1
,
groupW
,
len
*
sizeof
(
WCHAR
)
);
}
ret
=
EnumServicesStatusExW
(
hmngr
,
level
,
type
,
state
,
(
BYTE
*
)
servicesW
,
2
*
size
,
needed
,
returned
,
resume_handle
,
groupW
);
if
(
!
ret
)
goto
done
;
p
=
(
char
*
)
services
+
*
returned
*
sizeof
(
ENUM_SERVICE_STATUS_PROCESSA
);
n
=
size
-
(
p
-
(
char
*
)
services
);
ret
=
FALSE
;
for
(
i
=
0
;
i
<
*
returned
;
i
++
)
{
sz
=
WideCharToMultiByte
(
CP_ACP
,
0
,
servicesW
[
i
].
lpServiceName
,
-
1
,
p
,
n
,
NULL
,
NULL
);
if
(
!
sz
)
goto
done
;
services
[
i
].
lpServiceName
=
p
;
p
+=
sz
;
n
-=
sz
;
if
(
servicesW
[
i
].
lpDisplayName
)
{
sz
=
WideCharToMultiByte
(
CP_ACP
,
0
,
servicesW
[
i
].
lpDisplayName
,
-
1
,
p
,
n
,
NULL
,
NULL
);
if
(
!
sz
)
goto
done
;
services
[
i
].
lpDisplayName
=
p
;
p
+=
sz
;
n
-=
sz
;
}
services
[
i
].
ServiceStatusProcess
=
servicesW
[
i
].
ServiceStatusProcess
;
}
ret
=
TRUE
;
done:
HeapFree
(
GetProcessHeap
(),
0
,
servicesW
);
HeapFree
(
GetProcessHeap
(),
0
,
groupW
);
return
ret
;
}
/******************************************************************************
* EnumServicesStatusExW [ADVAPI32.@]
*/
BOOL
WINAPI
EnumServicesStatusExW
(
SC_HANDLE
hSCManager
,
SC_ENUM_TYPE
InfoLevel
,
DWORD
dwServiceType
,
DWORD
dwServiceState
,
LPBYTE
lpServices
,
DWORD
cbBufSize
,
LPDWORD
pcbBytesNeeded
,
LPDWORD
lpServicesReturned
,
LPDWORD
lpResumeHandle
,
LPCWSTR
pszGroupName
)
{
FIXME
(
"%p level=%d type=%x state=%x %p %x %p %p %p %s
\n
"
,
hSCManager
,
InfoLevel
,
dwServiceType
,
dwServiceState
,
lpServices
,
cbBufSize
,
pcbBytesNeeded
,
lpServicesReturned
,
lpResumeHandle
,
debugstr_w
(
pszGroupName
));
SetLastError
(
ERROR_ACCESS_DENIED
);
EnumServicesStatusExW
(
SC_HANDLE
hmngr
,
SC_ENUM_TYPE
level
,
DWORD
type
,
DWORD
state
,
LPBYTE
buffer
,
DWORD
size
,
LPDWORD
needed
,
LPDWORD
returned
,
LPDWORD
resume_handle
,
LPCWSTR
group
)
{
DWORD
err
,
i
;
ENUM_SERVICE_STATUS_PROCESSW
*
services
=
(
ENUM_SERVICE_STATUS_PROCESSW
*
)
buffer
;
TRACE
(
"%p %u 0x%x 0x%x %p %u %p %p %p %s
\n
"
,
hmngr
,
level
,
type
,
state
,
buffer
,
size
,
needed
,
returned
,
resume_handle
,
debugstr_w
(
group
));
if
(
resume_handle
)
FIXME
(
"resume handle not supported
\n
"
);
if
(
level
!=
SC_ENUM_PROCESS_INFO
)
{
SetLastError
(
ERROR_INVALID_LEVEL
);
return
FALSE
;
}
if
(
!
hmngr
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
__TRY
{
err
=
svcctl_EnumServicesStatusExW
(
hmngr
,
type
,
state
,
buffer
,
size
,
needed
,
returned
,
group
);
}
__EXCEPT
(
rpc_filter
)
{
err
=
map_exception_code
(
GetExceptionCode
()
);
}
__ENDTRY
if
(
err
!=
ERROR_SUCCESS
)
{
SetLastError
(
err
);
return
FALSE
;
}
for
(
i
=
0
;
i
<
*
returned
;
i
++
)
{
/* convert buffer offsets into pointers */
services
[
i
].
lpServiceName
=
(
WCHAR
*
)((
char
*
)
services
+
(
DWORD_PTR
)
services
[
i
].
lpServiceName
);
if
(
services
[
i
].
lpDisplayName
)
services
[
i
].
lpDisplayName
=
(
WCHAR
*
)((
char
*
)
services
+
(
DWORD_PTR
)
services
[
i
].
lpDisplayName
);
}
return
TRUE
;
}
/******************************************************************************
...
...
dlls/advapi32/tests/service.c
View file @
7135ac76
...
...
@@ -1398,7 +1398,6 @@ static void test_enum_svc(void)
SetLastError
(
0xdeadbeef
);
ret
=
pEnumServicesStatusExA
(
NULL
,
1
,
0
,
0
,
NULL
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
ok
(
GetLastError
()
==
ERROR_INVALID_LEVEL
,
"Expected ERROR_INVALID_LEVEL, got %d
\n
"
,
GetLastError
());
...
...
@@ -1406,7 +1405,6 @@ static void test_enum_svc(void)
SetLastError
(
0xdeadbeef
);
ret
=
pEnumServicesStatusExA
(
NULL
,
0
,
0
,
0
,
NULL
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
ok
(
GetLastError
()
==
ERROR_INVALID_HANDLE
,
"Expected ERROR_INVALID_HANDLE, got %d
\n
"
,
GetLastError
());
...
...
@@ -1417,7 +1415,6 @@ static void test_enum_svc(void)
SetLastError
(
0xdeadbeef
);
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
0
,
0
,
NULL
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
ok
(
GetLastError
()
==
ERROR_INVALID_ADDRESS
||
GetLastError
()
==
ERROR_INVALID_PARAMETER
/* NT4 */
,
"Unexpected last error %d
\n
"
,
GetLastError
());
...
...
@@ -1429,7 +1426,6 @@ static void test_enum_svc(void)
ok
(
!
ret
,
"Expected failure
\n
"
);
ok
(
needed
==
0xdeadbeef
||
broken
(
needed
!=
0xdeadbeef
),
/* nt4 */
"Expected no change to the needed buffer variable
\n
"
);
todo_wine
ok
(
GetLastError
()
==
ERROR_INVALID_ADDRESS
||
GetLastError
()
==
ERROR_INVALID_PARAMETER
/* NT4 */
,
"Unexpected last error %d
\n
"
,
GetLastError
());
...
...
@@ -1439,13 +1435,10 @@ static void test_enum_svc(void)
SetLastError
(
0xdeadbeef
);
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
0
,
0
,
NULL
,
0
,
NULL
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
{
ok
(
returned
==
0xdeadbeef
,
"Expected no change to the number of services variable
\n
"
);
ok
(
GetLastError
()
==
ERROR_INVALID_ADDRESS
||
GetLastError
()
==
ERROR_INVALID_PARAMETER
/* NT4 */
,
"Unexpected last error %d
\n
"
,
GetLastError
());
}
/* No valid servicetype and servicestate */
needed
=
0xdeadbeef
;
...
...
@@ -1454,13 +1447,10 @@ static void test_enum_svc(void)
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
0
,
0
,
NULL
,
0
,
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
ok
(
returned
==
0
,
"Expected number of service to be set to 0, got %d
\n
"
,
returned
);
todo_wine
{
ok
(
needed
==
0
||
broken
(
needed
!=
0
),
/* nt4 */
"Expected needed buffer size to be set to 0, got %d
\n
"
,
needed
);
ok
(
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"Expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
}
/* No valid servicestate */
needed
=
0xdeadbeef
;
...
...
@@ -1470,13 +1460,10 @@ static void test_enum_svc(void)
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
ok
(
returned
==
0
,
"Expected number of service to be set to 0, got %d
\n
"
,
returned
);
todo_wine
{
ok
(
needed
==
0
||
broken
(
needed
!=
0
),
/* nt4 */
"Expected needed buffer size to be set to 0, got %d
\n
"
,
needed
);
ok
(
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"Expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
}
/* No valid servicetype */
needed
=
0xdeadbeef
;
...
...
@@ -1486,13 +1473,10 @@ static void test_enum_svc(void)
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
ok
(
returned
==
0
,
"Expected number of service to be set to 0, got %d
\n
"
,
returned
);
todo_wine
{
ok
(
needed
==
0
||
broken
(
needed
!=
0
),
/* nt4 */
"Expected needed buffer size to be set to 0, got %d
\n
"
,
needed
);
ok
(
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"Expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
}
/* No valid servicetype and servicestate and unknown service group */
needed
=
0xdeadbeef
;
...
...
@@ -1502,13 +1486,10 @@ static void test_enum_svc(void)
&
returned
,
NULL
,
"deadbeef_group"
);
ok
(
!
ret
,
"Expected failure
\n
"
);
ok
(
returned
==
0
,
"Expected number of service to be set to 0, got %d
\n
"
,
returned
);
todo_wine
{
ok
(
needed
==
0
||
broken
(
needed
!=
0
),
/* nt4 */
"Expected needed buffer size to be set to 0, got %d
\n
"
,
needed
);
ok
(
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"Expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
}
/* All parameters are correct but our access rights are wrong */
needed
=
0xdeadbeef
;
...
...
@@ -1517,7 +1498,6 @@ static void test_enum_svc(void)
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
,
SERVICE_STATE_ALL
,
NULL
,
0
,
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
ok
(
needed
==
0
||
broken
(
needed
!=
0
),
/* nt4 */
"Expected needed buffer size to be set to 0, got %d
\n
"
,
needed
);
ok
(
returned
==
0
,
"Expected number of service to be set to 0, got %d
\n
"
,
returned
);
...
...
@@ -1533,7 +1513,6 @@ static void test_enum_svc(void)
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
,
SERVICE_STATE_ALL
,
NULL
,
0
,
&
needed
,
&
returned
,
NULL
,
"deadbeef_group"
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
ok
(
needed
==
0
||
broken
(
needed
!=
0
),
/* nt4 */
"Expected needed buffer size to be set to 0, got %d
\n
"
,
needed
);
ok
(
returned
==
0
,
"Expected number of service to be set to 0, got %d
\n
"
,
returned
);
...
...
@@ -1552,12 +1531,9 @@ static void test_enum_svc(void)
NULL
,
0
,
&
needed
,
&
returned
,
NULL
,
"deadbeef_group"
);
ok
(
!
ret
,
"Expected failure
\n
"
);
ok
(
returned
==
0
,
"Expected number of service to be set to 0, got %d
\n
"
,
returned
);
todo_wine
{
ok
(
needed
==
0
,
"Expected needed buffer size to be set to 0, got %d
\n
"
,
needed
);
ok
(
GetLastError
()
==
ERROR_SERVICE_DOES_NOT_EXIST
,
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d
\n
"
,
GetLastError
());
}
/* TODO: Create a test that makes sure we enumerate all services that don't
* belong to a group. (specifying "").
...
...
@@ -1571,12 +1547,9 @@ static void test_enum_svc(void)
NULL
,
0
,
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
ok
(
returned
==
0
,
"Expected no service returned, got %d
\n
"
,
returned
);
todo_wine
{
ok
(
needed
!=
0xdeadbeef
&&
needed
>
0
,
"Expected the needed buffer size
\n
"
);
ok
(
GetLastError
()
==
ERROR_MORE_DATA
,
"Expected ERROR_MORE_DATA, got %d
\n
"
,
GetLastError
());
}
/* Test to show we get the same needed buffer size for the W-call */
neededW
=
0xdeadbeef
;
...
...
@@ -1595,12 +1568,9 @@ static void test_enum_svc(void)
SetLastError
(
0xdeadbeef
);
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
,
SERVICE_STATE_ALL
,
(
BYTE
*
)
exservices
,
bufsize
,
&
needed
,
&
returned
,
NULL
,
NULL
);
todo_wine
{
ok
(
ret
,
"Expected success, got error %u
\n
"
,
GetLastError
());
ok
(
needed
==
0
,
"Expected needed buffer to be 0 as we are done
\n
"
);
ok
(
returned
==
tempreturned
,
"Expected the same number of service from this function
\n
"
);
}
HeapFree
(
GetProcessHeap
(),
0
,
exservices
);
/* Store the number of returned services */
...
...
@@ -1615,13 +1585,10 @@ static void test_enum_svc(void)
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
,
SERVICE_STATE_ALL
,
(
BYTE
*
)
exservices
,
bufsize
,
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
{
ok
(
needed
!=
0xdeadbeef
&&
needed
>
0
,
"Expected the needed buffer size
\n
"
);
ok
(
returned
<
tempreturned
,
"Expected fewer services to be returned
\n
"
);
ok
(
GetLastError
()
==
ERROR_MORE_DATA
,
"Expected ERROR_MORE_DATA, got %d
\n
"
,
GetLastError
());
}
/* Allocate less than the needed bytes, this time with a correct resume handle */
bufsize
=
(
tempreturned
-
1
)
*
sizeof
(
ENUM_SERVICE_STATUS
);
...
...
@@ -1632,14 +1599,11 @@ static void test_enum_svc(void)
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
,
SERVICE_STATE_ALL
,
(
BYTE
*
)
exservices
,
bufsize
,
&
needed
,
&
returned
,
&
resume
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
todo_wine
{
ok
(
needed
!=
0xdeadbeef
&&
needed
>
0
,
"Expected the needed buffer size
\n
"
);
ok
(
returned
<
tempreturned
,
"Expected fewer services to be returned
\n
"
);
ok
(
resume
,
"Expected a resume handle
\n
"
);
todo_wine
ok
(
resume
,
"Expected a resume handle
\n
"
);
ok
(
GetLastError
()
==
ERROR_MORE_DATA
,
"Expected ERROR_MORE_DATA, got %d
\n
"
,
GetLastError
());
}
/* Fetch that last service but pass a bigger buffer size */
missing
=
tempreturned
-
returned
;
...
...
@@ -1649,11 +1613,8 @@ static void test_enum_svc(void)
SetLastError
(
0xdeadbeef
);
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
,
SERVICE_STATE_ALL
,
(
BYTE
*
)
exservices
,
bufsize
,
&
needed
,
&
returned
,
&
resume
,
NULL
);
todo_wine
{
ok
(
ret
,
"Expected success, got error %u
\n
"
,
GetLastError
());
ok
(
needed
==
0
,
"Expected needed buffer to be 0 as we are done
\n
"
);
}
ok
(
returned
==
missing
,
"Expected %u services to be returned
\n
"
,
missing
);
ok
(
resume
==
0
,
"Expected the resume handle to be 0
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
exservices
);
...
...
@@ -1693,18 +1654,19 @@ static void test_enum_svc(void)
"Something wrong in the calculation
\n
"
);
/* Get all drivers and services */
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
|
SERVICE_DRIVER
,
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
|
SERVICE_DRIVER
,
SERVICE_STATE_ALL
,
NULL
,
0
,
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
!
ret
,
"Expected failure
\n
"
);
exservices
=
HeapAlloc
(
GetProcessHeap
(),
0
,
needed
);
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
|
SERVICE_DRIVER
,
ret
=
pEnumServicesStatusExA
(
scm_handle
,
0
,
SERVICE_WIN32
|
SERVICE_DRIVER
,
SERVICE_STATE_ALL
,
(
BYTE
*
)
exservices
,
needed
,
&
needed
,
&
returned
,
NULL
,
NULL
);
ok
(
ret
,
"Expected success %u
\n
"
,
GetLastError
());
/* Loop through all those returned drivers and services */
for
(
i
=
0
;
i
<
returned
;
i
++
)
{
SERVICE_STATUS_PROCESS
status
=
exservices
[
i
].
ServiceStatusProcess
;
/* lpServiceName and lpDisplayName should always be filled */
ok
(
lstrlenA
(
exservices
[
i
].
lpServiceName
)
>
0
,
"Expected a service name
\n
"
);
ok
(
lstrlenA
(
exservices
[
i
].
lpDisplayName
)
>
0
,
"Expected a display name
\n
"
);
...
...
include/wine/svcctl.idl
View file @
7135ac76
...
...
@@ -352,4 +352,15 @@ typedef [switch_type(DWORD)] union
[
in
]
DWORD
cbBufSize
,
[
out
]
LPDWORD
pcbBytesNeeded
)
;
DWORD
svcctl_EnumServicesStatusExW
(
[
in
]
SC_RPC_HANDLE
hmngr
,
[
in
]
DWORD
type
,
[
in
]
DWORD
state
,
[
out
,
size_is
(
size
)
]
BYTE
*
buffer
,
[
in
]
DWORD
size
,
[
out
]
LPDWORD
needed
,
[
out
]
LPDWORD
returned
,
[
in
,
unique
]
LPCWSTR
group
)
;
}
programs/services/rpc.c
View file @
7135ac76
...
...
@@ -1212,6 +1212,110 @@ DWORD svcctl_EnumServicesStatusW(
return
ERROR_SUCCESS
;
}
struct
service_entry
*
find_service_by_group
(
struct
scmdatabase
*
db
,
const
WCHAR
*
group
)
{
struct
service_entry
*
service
;
LIST_FOR_EACH_ENTRY
(
service
,
&
db
->
services
,
struct
service_entry
,
entry
)
{
if
(
service
->
config
.
lpLoadOrderGroup
&&
!
strcmpiW
(
group
,
service
->
config
.
lpLoadOrderGroup
))
return
service
;
}
return
NULL
;
}
static
BOOL
match_group
(
const
WCHAR
*
g1
,
const
WCHAR
*
g2
)
{
if
(
!
g2
)
return
TRUE
;
if
(
!
g2
[
0
]
&&
(
!
g1
||
!
g1
[
0
]))
return
TRUE
;
if
(
g1
&&
!
strcmpW
(
g1
,
g2
))
return
TRUE
;
return
FALSE
;
}
DWORD
svcctl_EnumServicesStatusExW
(
SC_RPC_HANDLE
hmngr
,
DWORD
type
,
DWORD
state
,
BYTE
*
buffer
,
DWORD
size
,
LPDWORD
needed
,
LPDWORD
returned
,
LPCWSTR
group
)
{
DWORD
err
,
sz
,
total_size
,
num_services
;
DWORD_PTR
offset
;
struct
sc_manager_handle
*
manager
;
struct
service_entry
*
service
;
ENUM_SERVICE_STATUS_PROCESSW
*
s
;
WINE_TRACE
(
"(%p, 0x%x, 0x%x, %p, %u, %p, %p, %s)
\n
"
,
hmngr
,
type
,
state
,
buffer
,
size
,
needed
,
returned
,
wine_dbgstr_w
(
group
));
if
(
!
type
||
!
state
)
return
ERROR_INVALID_PARAMETER
;
if
((
err
=
validate_scm_handle
(
hmngr
,
SC_MANAGER_ENUMERATE_SERVICE
,
&
manager
))
!=
ERROR_SUCCESS
)
return
err
;
scmdatabase_lock_exclusive
(
manager
->
db
);
if
(
group
&&
!
find_service_by_group
(
manager
->
db
,
group
))
{
scmdatabase_unlock
(
manager
->
db
);
return
ERROR_SERVICE_DOES_NOT_EXIST
;
}
total_size
=
num_services
=
0
;
LIST_FOR_EACH_ENTRY
(
service
,
&
manager
->
db
->
services
,
struct
service_entry
,
entry
)
{
if
((
service
->
status
.
dwServiceType
&
type
)
&&
map_state
(
service
->
status
.
dwCurrentState
,
state
)
&&
match_group
(
service
->
config
.
lpLoadOrderGroup
,
group
))
{
total_size
+=
sizeof
(
ENUM_SERVICE_STATUS_PROCESSW
);
total_size
+=
(
strlenW
(
service
->
name
)
+
1
)
*
sizeof
(
WCHAR
);
if
(
service
->
config
.
lpDisplayName
)
{
total_size
+=
(
strlenW
(
service
->
config
.
lpDisplayName
)
+
1
)
*
sizeof
(
WCHAR
);
}
num_services
++
;
}
}
*
returned
=
0
;
*
needed
=
total_size
;
if
(
total_size
>
size
)
{
scmdatabase_unlock
(
manager
->
db
);
return
ERROR_MORE_DATA
;
}
s
=
(
ENUM_SERVICE_STATUS_PROCESSW
*
)
buffer
;
offset
=
num_services
*
sizeof
(
ENUM_SERVICE_STATUS_PROCESSW
);
LIST_FOR_EACH_ENTRY
(
service
,
&
manager
->
db
->
services
,
struct
service_entry
,
entry
)
{
if
((
service
->
status
.
dwServiceType
&
type
)
&&
map_state
(
service
->
status
.
dwCurrentState
,
state
)
&&
match_group
(
service
->
config
.
lpLoadOrderGroup
,
group
))
{
sz
=
(
strlenW
(
service
->
name
)
+
1
)
*
sizeof
(
WCHAR
);
memcpy
(
buffer
+
offset
,
service
->
name
,
sz
);
s
->
lpServiceName
=
(
WCHAR
*
)
offset
;
/* store a buffer offset instead of a pointer */
offset
+=
sz
;
if
(
!
service
->
config
.
lpDisplayName
)
s
->
lpDisplayName
=
NULL
;
else
{
sz
=
(
strlenW
(
service
->
config
.
lpDisplayName
)
+
1
)
*
sizeof
(
WCHAR
);
memcpy
(
buffer
+
offset
,
service
->
config
.
lpDisplayName
,
sz
);
s
->
lpDisplayName
=
(
WCHAR
*
)
offset
;
offset
+=
sz
;
}
s
->
ServiceStatusProcess
=
service
->
status
;
s
++
;
}
}
*
returned
=
num_services
;
*
needed
=
0
;
scmdatabase_unlock
(
manager
->
db
);
return
ERROR_SUCCESS
;
}
DWORD
svcctl_QueryServiceObjectSecurity
(
void
)
{
...
...
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