Rob Shearman : services: svcctl_GetServiceDisplayNameW and svcctl_GetServiceKeyNameW should have string attribute on output buffer .

Alexandre Julliard julliard at winehq.org
Tue Mar 24 09:01:59 CDT 2009


Module: wine
Branch: master
Commit: 1c89dacf9c032e2d8e727f75eeb292c463fc2689
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1c89dacf9c032e2d8e727f75eeb292c463fc2689

Author: Rob Shearman <robertshearman at gmail.com>
Date:   Tue Mar 24 11:26:12 2009 +0000

services: svcctl_GetServiceDisplayNameW and svcctl_GetServiceKeyNameW should have string attribute on output buffer.

They also should not have two parameters for specifying the size of the buffer.

The buffer size should also not include in the nul-terminating character.

---

 dlls/advapi32/service.c |   22 ++++++++++++++++++++--
 include/wine/svcctl.idl |   10 ++++------
 programs/services/rpc.c |   30 ++++++++++++++++--------------
 3 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index 39a1afc..51a41e7 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -1568,6 +1568,7 @@ BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
 {
     DWORD err;
     WCHAR buffer[2];
+    DWORD size;
 
     TRACE("%p %s %p %p\n", hSCManager,
           debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
@@ -1588,10 +1589,14 @@ BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
         *lpcchBuffer = 2;
     }
 
+    /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
+     * includes the nul-terminator on input. */
+    size = *lpcchBuffer - 1;
+
     __TRY
     {
         err = svcctl_GetServiceKeyNameW(hSCManager, lpDisplayName, lpServiceName,
-                                        *lpcchBuffer, lpcchBuffer);
+                                        &size);
     }
     __EXCEPT(rpc_filter)
     {
@@ -1599,6 +1604,10 @@ BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
     }
     __ENDTRY
 
+    /* The value of *lpcchBuffer excludes nul-terminator on output. */
+    if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
+        *lpcchBuffer = size;
+
     if (err)
         SetLastError(err);
     return err == ERROR_SUCCESS;
@@ -1682,6 +1691,7 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
   LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
 {
     DWORD err;
+    DWORD size;
     WCHAR buffer[2];
 
     TRACE("%p %s %p %p\n", hSCManager,
@@ -1703,10 +1713,14 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
         *lpcchBuffer = 2;
     }
 
+    /* RPC call takes size excluding nul-terminator, whereas *lpcchBuffer
+     * includes the nul-terminator on input. */
+    size = *lpcchBuffer - 1;
+
     __TRY
     {
         err = svcctl_GetServiceDisplayNameW(hSCManager, lpServiceName, lpDisplayName,
-                                            *lpcchBuffer, lpcchBuffer);
+                                            &size);
     }
     __EXCEPT(rpc_filter)
     {
@@ -1714,6 +1728,10 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
     }
     __ENDTRY
 
+    /* The value of *lpcchBuffer excludes nul-terminator on output. */
+    if (err == ERROR_SUCCESS || err == ERROR_INSUFFICIENT_BUFFER)
+        *lpcchBuffer = size;
+
     if (err)
         SetLastError(err);
     return err == ERROR_SUCCESS;
diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl
index 1e9aae2..0414dc4 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -257,17 +257,15 @@ typedef [switch_type(DWORD)] union
     DWORD svcctl_GetServiceDisplayNameW(
         [in] SC_RPC_HANDLE hSCManager,
         [in] LPCWSTR lpServiceName,
-        [out,size_is(cchBufSize)] WCHAR lpBuffer[],
-        [in] DWORD cchBufSize,
-        [in,out] DWORD *cchLength);
+        [out,string,size_is(*cchBufSize+1)] WCHAR lpBuffer[],
+        [in,out] DWORD *cchBufSize);
 
     /* Compatible with Windows function 0x15 */
     DWORD svcctl_GetServiceKeyNameW(
         [in] SC_RPC_HANDLE hSCManager,
         [in] LPCWSTR lpServiceDisplayName,
-        [out,size_is(cchBufSize)] WCHAR lpBuffer[],
-        [in] DWORD cchBufSize,
-        [in,out] DWORD *cchLength);
+        [out,string,size_is(*cchBufSize+1)] WCHAR lpBuffer[],
+        [in,out] DWORD *cchBufSize);
 
     /* Not compatible with Windows function 0x16 */
     DWORD svcctl_SCSetServiceBitsA(/* FIXME */);
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 22391c2..d463b62 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -184,14 +184,13 @@ DWORD svcctl_GetServiceDisplayNameW(
     SC_RPC_HANDLE hSCManager,
     LPCWSTR lpServiceName,
     WCHAR *lpBuffer,
-    DWORD cchBufSize,
-    DWORD *cchLength)
+    DWORD *cchBufSize)
 {
     struct sc_manager_handle *manager;
     struct service_entry *entry;
     DWORD err;
 
-    WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceName), cchBufSize);
+    WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceName), *cchBufSize);
 
     if ((err = validate_scm_handle(hSCManager, 0, &manager)) != ERROR_SUCCESS)
         return err;
@@ -202,16 +201,18 @@ DWORD svcctl_GetServiceDisplayNameW(
     if (entry != NULL)
     {
         LPCWSTR name;
+        int len;
         service_lock_shared(entry);
         name = get_display_name(entry);
-        *cchLength = strlenW(name);
-        if (*cchLength < cchBufSize)
+        len = strlenW(name);
+        if (len <= *cchBufSize)
         {
             err = ERROR_SUCCESS;
-            lstrcpyW(lpBuffer, name);
+            memcpy(lpBuffer, name, (len + 1)*sizeof(*name));
         }
         else
             err = ERROR_INSUFFICIENT_BUFFER;
+        *cchBufSize = len;
         service_unlock(entry);
     }
     else
@@ -219,7 +220,7 @@ DWORD svcctl_GetServiceDisplayNameW(
 
     scmdatabase_unlock(manager->db);
 
-    if (err != ERROR_SUCCESS && cchBufSize > 0)
+    if (err != ERROR_SUCCESS)
         lpBuffer[0] = 0;
 
     return err;
@@ -229,14 +230,13 @@ DWORD svcctl_GetServiceKeyNameW(
     SC_RPC_HANDLE hSCManager,
     LPCWSTR lpServiceDisplayName,
     WCHAR *lpBuffer,
-    DWORD cchBufSize,
-    DWORD *cchLength)
+    DWORD *cchBufSize)
 {
     struct service_entry *entry;
     struct sc_manager_handle *manager;
     DWORD err;
 
-    WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceDisplayName), cchBufSize);
+    WINE_TRACE("(%s, %d)\n", wine_dbgstr_w(lpServiceDisplayName), *cchBufSize);
 
     if ((err = validate_scm_handle(hSCManager, 0, &manager)) != ERROR_SUCCESS)
         return err;
@@ -246,15 +246,17 @@ DWORD svcctl_GetServiceKeyNameW(
     entry = scmdatabase_find_service_by_displayname(manager->db, lpServiceDisplayName);
     if (entry != NULL)
     {
+        int len;
         service_lock_shared(entry);
-        *cchLength = strlenW(entry->name);
-        if (*cchLength < cchBufSize)
+        len = strlenW(entry->name);
+        if (len <= *cchBufSize)
         {
             err = ERROR_SUCCESS;
-            lstrcpyW(lpBuffer, entry->name);
+            memcpy(lpBuffer, entry->name, (len + 1)*sizeof(*entry->name));
         }
         else
             err = ERROR_INSUFFICIENT_BUFFER;
+        *cchBufSize = len;
         service_unlock(entry);
     }
     else
@@ -262,7 +264,7 @@ DWORD svcctl_GetServiceKeyNameW(
 
     scmdatabase_unlock(manager->db);
 
-    if (err != ERROR_SUCCESS && cchBufSize > 0)
+    if (err != ERROR_SUCCESS)
         lpBuffer[0] = 0;
 
     return err;




More information about the wine-cvs mailing list