Zebediah Figura : advapi32: Reimplement EnumServicesStatusW() on top of EnumServicesStatusExW().
Alexandre Julliard
julliard at winehq.org
Tue Apr 28 16:32:21 CDT 2020
Module: wine
Branch: master
Commit: d01f58a3f2cf48e5bb0728c9bb578f7d7f93bae4
URL: https://source.winehq.org/git/wine.git/?a=commit;h=d01f58a3f2cf48e5bb0728c9bb578f7d7f93bae4
Author: Zebediah Figura <z.figura12 at gmail.com>
Date: Mon Apr 27 22:35:34 2020 -0500
advapi32: Reimplement EnumServicesStatusW() on top of EnumServicesStatusExW().
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/advapi32/service.c | 124 ++++++++++++++++++------------------------
dlls/advapi32/tests/service.c | 2 +-
2 files changed, 54 insertions(+), 72 deletions(-)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index 4d32b44eef..eb195d84d0 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -1749,109 +1749,91 @@ done:
* EnumServicesStatusW [ADVAPI32.@]
*/
BOOL WINAPI
-EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW
- services, DWORD size, LPDWORD needed, LPDWORD returned,
- LPDWORD resume_handle )
+EnumServicesStatusW( SC_HANDLE manager, DWORD type, DWORD state, ENUM_SERVICE_STATUSW *status,
+ DWORD size, DWORD *ret_size, DWORD *ret_count, DWORD *resume_handle )
{
- DWORD err, i, offset, buflen, count, total_size = 0;
- struct enum_service_status *entry;
- const WCHAR *str;
- BYTE *buf;
+ ENUM_SERVICE_STATUS_PROCESSW *status_ex;
+ DWORD alloc_size, count, i;
+ WCHAR *p;
- TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", hmngr, type, state, services, size, needed,
- returned, resume_handle);
+ TRACE("%p 0x%x 0x%x %p %u %p %p %p\n", manager, type, state, status, size,
+ ret_size, ret_count, resume_handle);
- if (!hmngr)
+ if (!manager)
{
SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
- if (!needed || !returned)
+
+ if (!ret_size || !ret_count)
{
- SetLastError( ERROR_INVALID_ADDRESS );
+ SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
- /* make sure we pass a valid pointer */
- buflen = max( size, sizeof(*services) );
- if (!(buf = heap_alloc( buflen )))
+ *ret_size = 0;
+ *ret_count = 0;
+ if (!EnumServicesStatusExW( manager, SC_ENUM_PROCESS_INFO, type, state,
+ NULL, 0, &alloc_size, &count, resume_handle, NULL )
+ && GetLastError() != ERROR_MORE_DATA)
+ return FALSE;
+
+ if (!(status_ex = heap_alloc( alloc_size )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
- __TRY
+ if (!EnumServicesStatusExW( manager, SC_ENUM_PROCESS_INFO, type, state, (BYTE *)status_ex,
+ alloc_size, &alloc_size, &count, resume_handle, NULL )
+ && GetLastError() != ERROR_MORE_DATA)
{
- err = svcctl_EnumServicesStatusW( hmngr, type, state, buf, buflen, needed, &count, resume_handle );
- }
- __EXCEPT(rpc_filter)
- {
- err = map_exception_code( GetExceptionCode() );
+ heap_free( status_ex );
+ return FALSE;
}
- __ENDTRY
- *returned = 0;
- if (err != ERROR_SUCCESS)
+ for (i = 0; i < count; i++)
{
- /* double the needed size to fit the potentially larger ENUM_SERVICE_STATUSW */
- if (err == ERROR_MORE_DATA) *needed *= 2;
- heap_free( buf );
- SetLastError( err );
- return FALSE;
+ *ret_size += sizeof(ENUM_SERVICE_STATUSW);
+ *ret_size += (strlenW( status_ex[i].lpServiceName ) + 1) * sizeof(WCHAR);
+ if (status_ex[i].lpDisplayName)
+ *ret_size += (strlenW( status_ex[i].lpDisplayName ) + 1) * sizeof(WCHAR);
+
+ if (*ret_size <= size)
+ ++*ret_count;
}
- entry = (struct enum_service_status *)buf;
- for (i = 0; i < count; i++)
+ p = (WCHAR *)(status + *ret_count);
+ for (i = 0; i < *ret_count; i++)
{
- total_size += sizeof(*services);
- if (entry->service_name)
- {
- str = (const WCHAR *)(buf + entry->service_name);
- total_size += (strlenW( str ) + 1) * sizeof(WCHAR);
- }
- if (entry->display_name)
+ strcpyW( p, status_ex[i].lpServiceName );
+ status[i].lpServiceName = (WCHAR *)p;
+ p += strlenW( p ) + 1;
+ if (status_ex[i].lpDisplayName)
{
- str = (const WCHAR *)(buf + entry->display_name);
- total_size += (strlenW( str ) + 1) * sizeof(WCHAR);
+ strcpyW( p, status_ex[i].lpDisplayName );
+ status[i].lpDisplayName = (WCHAR *)p;
+ p += strlenW( p ) + 1;
}
- entry++;
+ else status[i].lpDisplayName = NULL;
+
+ status[i].ServiceStatus.dwServiceType = status_ex[i].ServiceStatusProcess.dwServiceType;
+ status[i].ServiceStatus.dwCurrentState = status_ex[i].ServiceStatusProcess.dwCurrentState;
+ status[i].ServiceStatus.dwControlsAccepted = status_ex[i].ServiceStatusProcess.dwControlsAccepted;
+ status[i].ServiceStatus.dwWin32ExitCode = status_ex[i].ServiceStatusProcess.dwWin32ExitCode;
+ status[i].ServiceStatus.dwServiceSpecificExitCode = status_ex[i].ServiceStatusProcess.dwServiceSpecificExitCode;
+ status[i].ServiceStatus.dwCheckPoint = status_ex[i].ServiceStatusProcess.dwCheckPoint;
+ status[i].ServiceStatus.dwWaitHint = status_ex[i].ServiceStatusProcess.dwWaitHint;
}
- if (total_size > size)
+ heap_free( status_ex );
+ if (*ret_size > size)
{
- heap_free( buf );
- *needed = total_size;
SetLastError( ERROR_MORE_DATA );
return FALSE;
}
- offset = count * sizeof(*services);
- entry = (struct enum_service_status *)buf;
- for (i = 0; i < count; i++)
- {
- DWORD str_size;
- str = (const WCHAR *)(buf + entry->service_name);
- str_size = (strlenW( str ) + 1) * sizeof(WCHAR);
- services[i].lpServiceName = (WCHAR *)((char *)services + offset);
- memcpy( services[i].lpServiceName, str, str_size );
- offset += str_size;
-
- if (!entry->display_name) services[i].lpDisplayName = NULL;
- else
- {
- str = (const WCHAR *)(buf + entry->display_name);
- str_size = (strlenW( str ) + 1) * sizeof(WCHAR);
- services[i].lpDisplayName = (WCHAR *)((char *)services + offset);
- memcpy( services[i].lpDisplayName, str, str_size );
- offset += str_size;
- }
- services[i].ServiceStatus = entry->service_status;
- entry++;
- }
-
- heap_free( buf );
- *needed = 0;
- *returned = count;
+ *ret_size = 0;
return TRUE;
}
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c
index 4bf9f4c34b..7048e5a09a 100644
--- a/dlls/advapi32/tests/service.c
+++ b/dlls/advapi32/tests/service.c
@@ -1339,7 +1339,7 @@ static void test_enum_svc(void)
services, bufsize, &needed, &returned, &resume);
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);
+ todo_wine 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, services);
More information about the wine-cvs
mailing list