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