Forward StartServiceA/W to services.exe
Modified: trunk/reactos/include/idl/svcctl.idl
Modified: trunk/reactos/lib/advapi32/service/scm.c
Modified: trunk/reactos/subsys/system/services/rpcserver.c

Modified: trunk/reactos/include/idl/svcctl.idl
--- trunk/reactos/include/idl/svcctl.idl	2005-12-31 11:22:44 UTC (rev 20479)
+++ trunk/reactos/include/idl/svcctl.idl	2005-12-31 11:33:46 UTC (rev 20480)
@@ -184,6 +184,13 @@
                                     [out] LPDWORD pcbBytesNeeded);
 
   /* Function 19 */
+  DWORD ScmrStartServiceW([in] handle_t BindingHandle,
+                          [in] SC_HANDLE hService,
+                          [in] DWORD dwNumServiceArgs,
+                          [in, size_is(cbBufSize)] LPBYTE lpServiceArgBuffer,
+                          [in] DWORD cbBufSize);
+
+  /* FIXME: This is the correct interface but WIDL doesn't support it yet! */
 //  DWORD ScmrStartServiceW([in] handle_t BindingHandle,
 //                          [in] SC_HANDLE hService,
 //                          [in] DWORD dwNumServiceArgs,
@@ -288,13 +295,20 @@
                                 [out] LPDWORD pcbBytesNeeded);
 
   /* Function 30 */
-//  DWORD ScmrQueryServiceLockStatusA([in] handle_t BindingHandle,
-//                                    [in] SC_HANDLE hSCManager,
-//                                    [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus,
-//                                    [in] DWORD cbBufSize,
-//                                    [out] LPDWORD pcbBytesNeeded);
+  DWORD ScmrQueryServiceLockStatusA([in] handle_t BindingHandle,
+                                    [in] SC_HANDLE hSCManager,
+                                    [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus,
+                                    [in] DWORD cbBufSize,
+                                    [out] LPDWORD pcbBytesNeeded);
 
   /* Function 31 */
+  DWORD ScmrStartServiceA([in] handle_t BindingHandle,
+                          [in] SC_HANDLE hService,
+                          [in] DWORD dwNumServiceArgs,
+                          [in, size_is(cbBufSize)] LPBYTE lpServiceArgBuffer,
+                          [in] DWORD cbBufSize);
+
+  /* FIXME: This is the correct interface but WIDL doesn't support it yet! */
 //  DWORD ScmrStartServiceA([in] handle_t BindingHandle,
 //                          [in] SC_HANDLE hService,
 //                          [in] DWORD dwNumServiceArgs,
@@ -314,20 +328,24 @@
                                [out, unique, size_is(*lpcchBuffer)] LPSTR lpServiceName,
                                [in, out, ref] LPDWORD lpcchBuffer);
 
-  /* Function 35 */
+  /* Function 34 */
   /* ScmrGetCurrentGroupStateW */
 
   /* Function 35 */
   /* ScmrEnumServiceGroupW */
 
   /* Function 36 */
-  /* ScmrChangeServiceConfig2A */
+//  DWORD ScmrChangeServiceConfig2A([in] handle_t BindingHandle,
+//                                  [in] SC_HANDLE hService,
+//                                  [in] DWORD dwInfoLevel,
+//                                  [in, size_is(dwInfoSize)] LPBYTE lpInfo,
+//                                  [in] DWORD dwInfoSize);
 
   /* Function 37 */
   DWORD ScmrChangeServiceConfig2W([in] handle_t BindingHandle,
                                   [in] SC_HANDLE hService,
                                   [in] DWORD dwInfoLevel,
-                                  [in, size_is(dwInfoSize)] unsigned char *lpInfo,
+                                  [in, size_is(dwInfoSize)] LPBYTE lpInfo,
                                   [in] DWORD dwInfoSize);
 
   /* Function 38 */

Modified: trunk/reactos/lib/advapi32/service/scm.c
--- trunk/reactos/lib/advapi32/service/scm.c	2005-12-31 11:22:44 UTC (rev 20479)
+++ trunk/reactos/lib/advapi32/service/scm.c	2005-12-31 11:33:46 UTC (rev 20480)
@@ -1557,32 +1557,89 @@
 /**********************************************************************
  *  StartServiceA
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-StartServiceA(
-    SC_HANDLE   hService,
-    DWORD       dwNumServiceArgs,
-    LPCSTR      *lpServiceArgVectors)
+BOOL STDCALL
+StartServiceA(SC_HANDLE hService,
+              DWORD dwNumServiceArgs,
+              LPCSTR *lpServiceArgVectors)
 {
-    DPRINT1("StartServiceA is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+#if 0
+    DWORD dwError;
+
+    DPRINT("StartServiceA()\n");
+
+    HandleBind();
+
+    /* Call to services.exe using RPC */
+    dwError = ScmrStartServiceA(BindingHandle,
+                                hService,
+                                dwNumServiceArgs,
+                                lpServiceArgVectors);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrStartServiceA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
+#endif
+    LPSTR lpBuffer;
+    LPSTR lpStr;
+    DWORD dwError;
+    DWORD dwBufSize;
+    DWORD i;
+
+    dwBufSize = 0;
+    for (i = 0; i < dwNumServiceArgs; i++)
+    {
+        dwBufSize += (strlen(lpServiceArgVectors[i]) + 1);
+    }
+    DPRINT1("dwBufSize: %lu\n", dwBufSize);
+
+    lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwBufSize);
+    if (lpBuffer == NULL)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    lpStr = lpBuffer;
+    for (i = 0; i < dwNumServiceArgs; i++)
+    {
+        strcpy(lpStr, lpServiceArgVectors[i]);
+        lpStr += (strlen(lpServiceArgVectors[i]) + 1);
+    }
+
+    dwError = ScmrStartServiceA(BindingHandle,
+                                (unsigned int)hService,
+                                dwNumServiceArgs,
+                                (unsigned char *)lpBuffer,
+                                dwBufSize);
+
+    HeapFree(GetProcessHeap(), 0, lpBuffer);
+
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrStartServiceA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 
 /**********************************************************************
  *  StartServiceW
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-StartServiceW(
-    SC_HANDLE   hService,
-    DWORD       dwNumServiceArgs,
-    LPCWSTR     *lpServiceArgVectors)
+BOOL STDCALL
+StartServiceW(SC_HANDLE hService,
+              DWORD dwNumServiceArgs,
+              LPCWSTR *lpServiceArgVectors)
 {
 #if 0
     DWORD dwError;
@@ -1593,6 +1650,7 @@
 
     /* Call to services.exe using RPC */
     dwError = ScmrStartServiceW(BindingHandle,
+                                hService,
                                 dwNumServiceArgs,
                                 lpServiceArgVectors);
     if (dwError != ERROR_SUCCESS)
@@ -1604,9 +1662,48 @@
 
     return TRUE;
 #endif
-    DPRINT1("StartServiceW is unimplemented, but returns success...\n");
-    //SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    //return FALSE;
+    LPWSTR lpBuffer;
+    LPWSTR lpStr;
+    DWORD dwError;
+    DWORD dwBufSize;
+    DWORD i;
+
+    dwBufSize = 0;
+    for (i = 0; i < dwNumServiceArgs; i++)
+    {
+        dwBufSize += ((wcslen(lpServiceArgVectors[i]) + 1) * sizeof(WCHAR));
+    }
+    DPRINT1("dwBufSize: %lu\n", dwBufSize);
+
+    lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwBufSize);
+    if (lpBuffer == NULL)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    lpStr = lpBuffer;
+    for (i = 0; i < dwNumServiceArgs; i++)
+    {
+        wcscpy(lpStr, lpServiceArgVectors[i]);
+        lpStr += (wcslen(lpServiceArgVectors[i]) + 1);
+    }
+
+    dwError = ScmrStartServiceW(BindingHandle,
+                                (unsigned int)hService,
+                                dwNumServiceArgs,
+                                (unsigned char *)lpBuffer,
+                                dwBufSize);
+
+    HeapFree(GetProcessHeap(), 0, lpBuffer);
+
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrStartServiceW() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
     return TRUE;
 }
 

Modified: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-12-31 11:22:44 UTC (rev 20479)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-12-31 11:33:46 UTC (rev 20480)
@@ -1730,9 +1730,55 @@
 
 
 /* Function 19 */
-/* ScmrStartServiceW */
+unsigned long
+ScmrStartServiceW(handle_t BindingHandle,
+                  unsigned int hService,
+                  unsigned long dwNumServiceArgs,
+                  unsigned char *lpServiceArgBuffer,
+                  unsigned long cbBufSize)
+{
+    DWORD dwError = ERROR_SUCCESS;
+    PSERVICE_HANDLE hSvc;
+    PSERVICE lpService = NULL;
 
+    DPRINT1("ScmrStartServiceW() called\n");
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
+    hSvc = (PSERVICE_HANDLE)hService;
+    if (hSvc->Handle.Tag != SERVICE_TAG)
+    {
+        DPRINT1("Invalid handle tag!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+                                  SERVICE_START))
+    {
+        DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+        return ERROR_ACCESS_DENIED;
+    }
+
+    lpService = hSvc->ServiceEntry;
+    if (lpService == NULL)
+    {
+        DPRINT1("lpService == NULL!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    if (lpService->dwStartType == SERVICE_DISABLED)
+        return ERROR_SERVICE_DISABLED;
+
+    if (lpService->bDeleted)
+        return ERROR_SERVICE_MARKED_FOR_DELETE;
+
+    /* FIXME: Start the service */
+
+    return dwError;
+}
+
+
 /* Function 20 */
 unsigned long
 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
@@ -2019,7 +2065,17 @@
 
 
 /* Function 31 */
-/* ScmrStartServiceA */
+unsigned long
+ScmrStartServiceA(handle_t BindingHandle,
+                  unsigned int hService,
+                  unsigned long dwNumServiceArgs,
+                  unsigned char *lpServiceArgBuffer,
+                  unsigned long cbBufSize)
+{
+    DPRINT1("ScmrStartServiceA() called\n");
+    return ERROR_SUCCESS;
+//    return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
 
 /* Function 32 */