- Initial hacky implementation of some SCM calls needed by coLinux.
authorFilip Navara <filip.navara@gmail.com>
Mon, 12 Apr 2004 17:14:55 +0000 (17:14 +0000)
committerFilip Navara <filip.navara@gmail.com>
Mon, 12 Apr 2004 17:14:55 +0000 (17:14 +0000)
svn path=/trunk/; revision=9110

reactos/include/services/scmprot.h [new file with mode: 0644]
reactos/lib/advapi32/service/scm.c
reactos/subsys/system/services/database.c
reactos/subsys/system/services/services.c
reactos/subsys/system/services/services.h

diff --git a/reactos/include/services/scmprot.h b/reactos/include/services/scmprot.h
new file mode 100644 (file)
index 0000000..12d6f8a
--- /dev/null
@@ -0,0 +1,115 @@
+/* 
+ * Service Control Manager - Protocol Header
+ *
+ * Copyright (C) 2004 Filip Navara
+ *
+ * This software is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.LIB. If not, write
+ * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ * MA 02139, USA.  
+ * 
+ * $Id: scmprot.h,v 1.1 2004/04/12 17:14:26 navaraf Exp $
+ */
+
+#ifndef _SCM_H
+#define _SCM_H
+
+/*
+ * NOTE:
+ * This protocol isn't compatible with the Windows (R) one. Since
+ * Windows (R) XP (or 2000?) all the communcation goes through RPC.
+ * We don't have RPC implemented yet, so it can't be used yet :(
+ */
+
+typedef struct
+{
+    ULONG Length;
+    WCHAR Buffer[256];
+} SCM_STRING;
+
+#define INIT_SCM_STRING(x, y) x.Length = wcslen(y) * sizeof(WCHAR), RtlCopyMemory(x.Buffer, y, x.Length + sizeof(UNICODE_NULL))
+
+/*
+ * Global requests
+ */
+
+#define SCM_OPENSERVICE                0x14
+#define SCM_CREATESERVICE      0x20
+
+typedef struct _SCM_OPENSERVICE_REQUEST
+{
+    DWORD RequestCode;
+    SCM_STRING ServiceName;
+    DWORD dwDesiredAccess;
+} SCM_OPENSERVICE_REQUEST, *PSCM_OPENSERVICE_REQUEST;
+
+typedef struct _SCM_OPENSERVICE_REPLY
+{
+    DWORD ReplyStatus;
+    WCHAR PipeName[128];
+} SCM_OPENSERVICE_REPLY, *PSCM_OPENSERVICE_REPLY;
+
+typedef struct _SCM_CREATESERVICE_REQUEST
+{
+    DWORD RequestCode;
+    SCM_STRING ServiceName;
+    SCM_STRING DisplayName;
+    DWORD dwDesiredAccess;
+    DWORD dwServiceType;
+    DWORD dwStartType;
+    DWORD dwErrorControl;
+    SCM_STRING BinaryPathName;
+    SCM_STRING LoadOrderGroup;
+    SCM_STRING Dependencies;
+    SCM_STRING ServiceStartName;
+    SCM_STRING Password;
+} SCM_CREATESERVICE_REQUEST, *PSCM_CREATESERVICE_REQUEST;
+
+typedef struct _SCM_CREATESERVICE_REPLY
+{
+    DWORD ReplyStatus;
+    WCHAR PipeName[128];
+} SCM_CREATESERVICE_REPLY, *PSCM_CREATESERVICE_REPLY;
+
+typedef union _SCM_REQUEST
+{
+    DWORD RequestCode;
+    SCM_OPENSERVICE_REQUEST OpenService;
+    SCM_CREATESERVICE_REQUEST CreateService;
+} SCM_REQUEST, *PSCM_REQUEST;
+
+typedef union _SCM_REPLY
+{
+    DWORD ReplyStatus;
+    SCM_OPENSERVICE_REPLY OpenService;
+    SCM_CREATESERVICE_REPLY CreateService;
+} SCM_REPLY, *PSCM_REPLY;
+
+/*
+ * Per service requests
+ */
+
+#define SCM_DELETESERVICE      0x10
+#define SCM_STARTSERVICE       0x11
+
+typedef union _SCM_SERVICE_REQUEST
+{
+    DWORD RequestCode;
+} SCM_SERVICE_REQUEST, *PSCM_SERVICE_REQUEST;
+
+typedef union _SCM_SERVICE_REPLY
+{
+    DWORD ReplyStatus;
+} SCM_SERVICE_REPLY, *PSCM_SERVICE_REPLY;
+
+#endif
index ae519b7..298b9f6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: scm.c,v 1.19 2003/08/07 04:03:22 royce Exp $
+/* $Id: scm.c,v 1.20 2004/04/12 17:14:54 navaraf Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -17,8 +17,9 @@
 #include <windows.h>
 #include <wchar.h>
 #include <tchar.h>
+#include <services/scmprot.h>
 
-#define DBG
+//#define DBG
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
@@ -82,14 +83,14 @@ BOOL
 STDCALL
 CloseServiceHandle(SC_HANDLE hSCObject)
 {
-    HANDLE hPipe;
-    DPRINT("CloseServiceHandle() - called.\n");
-//    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    DPRINT("CloseServiceHandle\n");
 
-    if (!CloseHandle(hPipe)) {
+    if (!CloseHandle(hSCObject))
+    {
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
+
     return TRUE;
 }
 
@@ -132,8 +133,48 @@ CreateServiceA(
     LPCSTR      lpServiceStartName,
     LPCSTR      lpPassword)
 {
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return NULL;
+    UNICODE_STRING lpServiceNameW;
+    UNICODE_STRING lpDisplayNameW;
+    UNICODE_STRING lpBinaryPathNameW;
+    UNICODE_STRING lpLoadOrderGroupW;
+    UNICODE_STRING lpServiceStartNameW;
+    UNICODE_STRING lpPasswordW;
+    SC_HANDLE hService;
+
+    RtlCreateUnicodeStringFromAsciiz(&lpServiceNameW, (LPSTR)lpServiceName);
+    RtlCreateUnicodeStringFromAsciiz(&lpDisplayNameW, (LPSTR)lpDisplayName);
+    RtlCreateUnicodeStringFromAsciiz(&lpBinaryPathNameW, (LPSTR)lpBinaryPathName);
+    RtlCreateUnicodeStringFromAsciiz(&lpLoadOrderGroupW, (LPSTR)lpLoadOrderGroup);
+    RtlCreateUnicodeStringFromAsciiz(&lpServiceStartNameW, (LPSTR)lpServiceStartName);
+    RtlCreateUnicodeStringFromAsciiz(&lpPasswordW, (LPSTR)lpPassword);
+    if (lpDependencies != NULL)
+    {
+       DPRINT1("Unimplemented case\n");
+    }
+
+    hService = CreateServiceW(
+        hSCManager,
+        lpServiceNameW.Buffer,
+        lpDisplayNameW.Buffer,
+        dwDesiredAccess,
+        dwServiceType,
+        dwStartType,
+        dwErrorControl,
+        lpBinaryPathNameW.Buffer,
+        lpLoadOrderGroupW.Buffer,
+        lpdwTagId,
+        NULL,
+        lpServiceStartNameW.Buffer,
+        lpPasswordW.Buffer);
+
+    RtlFreeUnicodeString(&lpServiceNameW);
+    RtlFreeUnicodeString(&lpDisplayNameW);
+    RtlFreeUnicodeString(&lpBinaryPathNameW);
+    RtlFreeUnicodeString(&lpLoadOrderGroupW);
+    RtlFreeUnicodeString(&lpServiceStartNameW);
+    RtlFreeUnicodeString(&lpPasswordW);
+
+    return hService;
 }
 
 
@@ -159,8 +200,104 @@ CreateServiceW(
     LPCWSTR     lpServiceStartName,
     LPCWSTR     lpPassword)
 {
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return NULL;
+    SCM_CREATESERVICE_REQUEST Request;
+    SCM_CREATESERVICE_REPLY Reply;
+    BOOL fSuccess;
+    DWORD cbWritten, cbRead;
+    SC_HANDLE hService;
+
+    DPRINT("CreateServiceW\n");
+
+    if (lpServiceName == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    Request.RequestCode = SCM_CREATESERVICE;
+    INIT_SCM_STRING(Request.ServiceName, lpServiceName);
+    INIT_SCM_STRING(Request.DisplayName, lpDisplayName);
+    Request.dwDesiredAccess = dwDesiredAccess;
+    Request.dwServiceType = dwServiceType;
+    Request.dwStartType = dwStartType;
+    Request.dwErrorControl = dwErrorControl;
+#if 0
+    INIT_SCM_STRING(Request.BinaryPathName, lpBinaryPathName);
+#else
+    Request.BinaryPathName.Length = (wcslen(lpBinaryPathName) + 4) * sizeof(WCHAR);
+    swprintf(Request.BinaryPathName.Buffer, L"\\??\\%s", lpBinaryPathName);
+#endif
+    INIT_SCM_STRING(Request.LoadOrderGroup, lpLoadOrderGroup);
+    INIT_SCM_STRING(Request.ServiceStartName, lpServiceStartName);
+    INIT_SCM_STRING(Request.Password, lpPassword);
+    if (lpDependencies != NULL)
+    {
+        DWORD Length;
+        for (Length = 0;
+             lpDependencies[Length++];
+             Length += lstrlenW(&lpDependencies[Length]) + 1)
+            ;
+        Request.Dependencies.Length = Length;
+    }
+    else
+    {
+        Request.Dependencies.Length = 0;
+    }
+    RtlCopyMemory(
+        Request.Dependencies.Buffer,
+        lpDependencies,
+        Request.Dependencies.Length);
+
+    fSuccess = WriteFile(
+        hSCManager,       // pipe handle
+        &Request,         // message
+        sizeof(Request),  // message length
+        &cbWritten,       // bytes written
+        NULL);            // not overlapped
+
+    if (!fSuccess || cbWritten != sizeof(Request))
+    {
+        DPRINT("CreateServiceW - Failed to write to pipe.\n");
+        return NULL;
+    }
+      
+    fSuccess = ReadFile(
+        hSCManager,       // pipe handle
+        &Reply,           // buffer to receive reply
+        sizeof(Reply),    // size of buffer
+        &cbRead,          // number of bytes read
+        NULL);            // not overlapped
+         
+    if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
+    {
+        DPRINT("CreateServiceW - Error\n");
+        return NULL;
+    }
+         
+    if (Reply.ReplyStatus != NO_ERROR)
+    {
+        DPRINT("CreateServiceW - Error (%x)\n", Reply.ReplyStatus);
+        SetLastError(Reply.ReplyStatus);
+        return NULL;
+    }
+
+    hService = CreateFileW(
+        Reply.PipeName,   // pipe name
+        FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+        0,                // no sharing
+        NULL,             // no security attributes
+        OPEN_EXISTING,    // opens existing pipe
+        0,                // default attributes
+        NULL);            // no template file
+
+    if (hService == INVALID_HANDLE_VALUE)
+    {
+        /* FIXME: Set last error! */
+        return NULL;
+    }
+
+    DPRINT("CreateServiceW - Success - %x\n", hService);
+    return hService;
 }
 
 
@@ -173,8 +310,51 @@ BOOL
 STDCALL
 DeleteService(SC_HANDLE hService)
 {
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    SCM_SERVICE_REQUEST Request;
+    SCM_SERVICE_REPLY Reply;
+    BOOL fSuccess;
+    DWORD cbWritten, cbRead;
+
+    DPRINT("DeleteService\n");
+
+    Request.RequestCode = SCM_DELETESERVICE;
+
+    fSuccess = WriteFile(
+        hService,         // pipe handle
+        &Request,         // message
+        sizeof(DWORD),    // message length
+        &cbWritten,       // bytes written
+        NULL);            // not overlapped
+
+    if (!fSuccess || cbWritten != sizeof(DWORD))
+    {
+        DPRINT("Error: %x . %x\n", GetLastError(), hService);
+        /* FIXME: Set last error */
+        return FALSE;
+    }
+      
+    fSuccess = ReadFile(
+        hService,         // pipe handle
+        &Reply,           // buffer to receive reply
+        sizeof(DWORD),    // size of buffer
+        &cbRead,          // number of bytes read
+        NULL);            // not overlapped
+         
+    if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
+    {
+        CHECKPOINT;
+        /* FIXME: Set last error */
+        return FALSE;
+    }
+         
+    if (Reply.ReplyStatus != NO_ERROR)
+    {
+        CHECKPOINT;
+        SetLastError(Reply.ReplyStatus);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 
@@ -634,22 +814,34 @@ SC_HANDLE STDCALL OpenSCManagerW(LPCWSTR lpMachineName,
 /**********************************************************************
  *  OpenServiceA
  *
- * @unimplemented
+ * @implemented
  */
-SC_HANDLE STDCALL
-OpenServiceA(SC_HANDLE hSCManager,
-         LPCSTR  lpServiceName,
-         DWORD dwDesiredAccess)
+SC_HANDLE
+STDCALL
+OpenServiceA(
+    SC_HANDLE hSCManager,
+    LPCSTR lpServiceName,
+    DWORD dwDesiredAccess
+    )
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return NULL;
+    UNICODE_STRING lpServiceNameW;
+    SC_HANDLE hService;
+
+    RtlCreateUnicodeStringFromAsciiz(&lpServiceNameW, (LPSTR)lpServiceName);
+    hService = OpenServiceW(
+        hSCManager,
+        lpServiceNameW.Buffer,
+        dwDesiredAccess);
+    RtlFreeUnicodeString(&lpServiceNameW);
+
+    return hService;
 }
 
 
 /**********************************************************************
  *  OpenServiceW
  *
- * @unimplemented
+ * @implemented
  */
 SC_HANDLE
 STDCALL
@@ -659,8 +851,74 @@ OpenServiceW(
     DWORD       dwDesiredAccess
     )
 {
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return NULL;
+    SCM_OPENSERVICE_REQUEST Request;
+    SCM_OPENSERVICE_REPLY Reply;
+    BOOL fSuccess;
+    DWORD cbWritten, cbRead;
+    SC_HANDLE hService;
+
+    DPRINT("OpenServiceW\n");
+
+    if (lpServiceName == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    Request.RequestCode = SCM_OPENSERVICE;
+    INIT_SCM_STRING(Request.ServiceName, lpServiceName);
+    Request.dwDesiredAccess = dwDesiredAccess;
+
+    fSuccess = WriteFile(
+        hSCManager,       // pipe handle
+        &Request,         // message
+        sizeof(Request),  // message length
+        &cbWritten,       // bytes written
+        NULL);            // not overlapped
+
+    if (!fSuccess || cbWritten != sizeof(Request))
+    {
+        DPRINT("OpenServiceW - Failed to write to pipe.\n");
+        return NULL;
+    }
+      
+    fSuccess = ReadFile(
+        hSCManager,       // pipe handle
+        &Reply,           // buffer to receive reply
+        sizeof(Reply),    // size of buffer
+        &cbRead,          // number of bytes read
+        NULL);            // not overlapped
+         
+    if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
+    {
+        DPRINT("OpenServiceW - Failed to read from pipe\n");
+        return NULL;
+    }
+         
+    if (Reply.ReplyStatus != NO_ERROR)
+    {
+        DPRINT("OpenServiceW - Error (%x)\n", Reply.ReplyStatus);
+        SetLastError(Reply.ReplyStatus);
+        return NULL;
+    }
+
+    hService = CreateFileW(
+        Reply.PipeName,   // pipe name
+        FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+        0,                // no sharing
+        NULL,             // no security attributes
+        OPEN_EXISTING,    // opens existing pipe
+        0,                // default attributes
+        NULL);            // no template file
+
+    if (hService == INVALID_HANDLE_VALUE)
+    {
+        DPRINT("OpenServiceW - Failed to connect to pipe\n");
+        return NULL;
+    }
+
+    DPRINT("OpenServiceW - Success - %x\n", hService);
+    return hService;
 }
 
 
@@ -801,8 +1059,63 @@ StartServiceA(
     DWORD       dwNumServiceArgs,
     LPCSTR      *lpServiceArgVectors)
 {
+#if 0
+    DPRINT("StartServiceA\n");
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     return FALSE;
+#else
+    SCM_SERVICE_REQUEST Request;
+    SCM_SERVICE_REPLY Reply;
+    BOOL fSuccess;
+    DWORD cbWritten, cbRead;
+
+    DPRINT("StartServiceA\n");
+
+    if (dwNumServiceArgs != 0)
+    {
+       UNIMPLEMENTED;
+    }
+
+    Request.RequestCode = SCM_STARTSERVICE;
+
+    fSuccess = WriteFile(
+        hService,         // pipe handle
+        &Request,         // message
+        sizeof(DWORD),    // message length
+        &cbWritten,       // bytes written
+        NULL);            // not overlapped
+
+    if (!fSuccess || cbWritten != sizeof(DWORD))
+    {
+        DPRINT("Error: %x . %x\n", GetLastError(), hService);
+        /* FIXME: Set last error */
+        return FALSE;
+    }
+      
+    fSuccess = ReadFile(
+        hService,         // pipe handle
+        &Reply,           // buffer to receive reply
+        sizeof(DWORD),    // size of buffer
+        &cbRead,          // number of bytes read
+        NULL);            // not overlapped
+         
+    if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
+    {
+        CHECKPOINT;
+        /* FIXME: Set last error */
+        return FALSE;
+    }
+         
+    if (Reply.ReplyStatus != NO_ERROR)
+    {
+        CHECKPOINT;
+        SetLastError(Reply.ReplyStatus);
+        return FALSE;
+    }
+
+    CHECKPOINT;
+    return TRUE;
+#endif
 }
 
 
@@ -820,6 +1133,7 @@ StartServiceW(
     DWORD       dwNumServiceArgs,
     LPCWSTR     *lpServiceArgVectors)
 {
+    DPRINT("StartServiceW\n");
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     return FALSE;
 }
index e318536..b0fd0bd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: database.c,v 1.14 2004/04/11 16:10:05 jfilby Exp $
+/* $Id: database.c,v 1.15 2004/04/12 17:14:54 navaraf Exp $
  *
  * service control manager
  * 
 #include <debug.h>
 
 
-/* TYPES *********************************************************************/
-
-typedef struct _SERVICE_GROUP
-{
-  LIST_ENTRY GroupListEntry;
-  UNICODE_STRING GroupName;
-
-  BOOLEAN ServicesRunning;
-
-} SERVICE_GROUP, *PSERVICE_GROUP;
-
-
-typedef struct _SERVICE
-{
-  LIST_ENTRY ServiceListEntry;
-  UNICODE_STRING ServiceName;
-  UNICODE_STRING RegistryPath;
-  UNICODE_STRING ServiceGroup;
-
-  ULONG Start;
-  ULONG Type;
-  ULONG ErrorControl;
-  ULONG Tag;
-
-  BOOLEAN ServiceRunning;
-  BOOLEAN ServiceVisited;
-
-  HANDLE ControlPipeHandle;
-  ULONG ProcessId;
-  ULONG ThreadId;
-} SERVICE, *PSERVICE;
-
-
 /* GLOBALS *******************************************************************/
 
 LIST_ENTRY GroupListHead;
@@ -116,8 +83,8 @@ CreateGroupListRoutine(PWSTR ValueName,
 }
 
 
-static NTSTATUS STDCALL
-CreateServiceListEntry(PUNICODE_STRING ServiceName)
+PSERVICE FASTCALL
+ScmCreateServiceListEntry(PUNICODE_STRING ServiceName)
 {
   RTL_QUERY_REGISTRY_TABLE QueryTable[6];
   PSERVICE Service = NULL;
@@ -130,7 +97,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
                      sizeof(SERVICE));
   if (Service == NULL)
     {
-      return(STATUS_INSUFFICIENT_RESOURCES);
+      return NULL;
     }
 
   /* Copy service name */
@@ -141,7 +108,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
   if (Service->ServiceName.Buffer == NULL)
     {
       HeapFree(GetProcessHeap(), 0, Service);
-      return(STATUS_INSUFFICIENT_RESOURCES);
+      return NULL;
     }
   RtlCopyMemory(Service->ServiceName.Buffer,
                ServiceName->Buffer,
@@ -156,7 +123,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
     {
       HeapFree(GetProcessHeap(), 0, Service->ServiceName.Buffer);
       HeapFree(GetProcessHeap(), 0, Service);
-      return(STATUS_INSUFFICIENT_RESOURCES);
+      return NULL;
     }
   wcscpy(Service->RegistryPath.Buffer,
         L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
@@ -195,7 +162,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
       RtlFreeUnicodeString(&Service->RegistryPath);
       RtlFreeUnicodeString(&Service->ServiceName);
       HeapFree(GetProcessHeap(), 0, Service);
-      return(Status);
+      return NULL;
     }
 
   DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
@@ -208,7 +175,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
   InsertTailList(&ServiceListHead,
                 &Service->ServiceListEntry);
 
-  return(STATUS_SUCCESS);
+  return Service;
 }
 
 
@@ -293,7 +260,10 @@ ScmCreateServiceDataBase(VOID)
              SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
 
              DPRINT("KeyName: '%wZ'\n", &SubKeyName);
-             Status = CreateServiceListEntry(&SubKeyName);
+             if (ScmCreateServiceListEntry(&SubKeyName) == NULL)
+               {
+                 return STATUS_INSUFFICIENT_RESOURCES;
+               }
            }
        }
 
@@ -446,7 +416,7 @@ ScmGetBootAndSystemDriverState(VOID)
 }
 
 
-static NTSTATUS
+NTSTATUS FASTCALL
 ScmStartService(PSERVICE Service,
                PSERVICE_GROUP Group)
 {
@@ -625,7 +595,7 @@ Done:
     }
 #endif
 
-  return(STATUS_SUCCESS);
+  return Status; //(STATUS_SUCCESS);
 }
 
 
@@ -720,4 +690,27 @@ ScmAutoStartServices(VOID)
     }
 }
 
+/*
+ * FIXME: Doesn't work!!!
+ */
+PSERVICE FASTCALL
+ScmFindService(PUNICODE_STRING ServiceName)
+{
+  PSERVICE CurrentService;
+  PLIST_ENTRY ServiceEntry;
+
+  ServiceEntry = ServiceListHead.Flink;
+  while (ServiceEntry != &ServiceListHead)
+    {
+      CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
+      if (!RtlCompareUnicodeString(ServiceName, &CurrentService->ServiceName, TRUE))
+        {
+          return CurrentService;
+        }
+      ServiceEntry = ServiceEntry->Flink;
+    }
+
+  return NULL;
+}
+
 /* EOF */
index c092450..03a2771 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: services.c,v 1.16 2004/04/12 15:22:53 navaraf Exp $
+/* $Id: services.c,v 1.17 2004/04/12 17:14:55 navaraf Exp $
  *
  * service control manager
  * 
 #include <ntos.h>
 #include <stdio.h>
 #include <windows.h>
+#undef CreateService
+#undef OpenService
 
 #include "services.h"
+#include <services/scmprot.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -43,8 +46,7 @@
 
 /* GLOBALS ******************************************************************/
 
-#define PIPE_BUFSIZE 1024
-#define PIPE_TIMEOUT 1000
+#define PIPE_TIMEOUT 10000
 
 
 /* FUNCTIONS *****************************************************************/
@@ -91,17 +93,461 @@ ScmCreateStartEvent(PHANDLE StartEvent)
 }
 
 
+typedef struct _SERVICE_THREAD_DATA
+{
+    HANDLE hPipe;
+    PSERVICE pService;
+} SERVICE_THREAD_DATA, *PSERVICE_THREAD_DATA;
+
+
+VOID FASTCALL
+ScmHandleDeleteServiceRequest(
+    PSERVICE_THREAD_DATA pServiceThreadData,
+    PSCM_SERVICE_REQUEST Request,
+    DWORD RequestSize,
+    PSCM_SERVICE_REPLY Reply,
+    LPDWORD ReplySize)
+{
+    Reply->ReplyStatus = RtlNtStatusToDosError(
+        ScmStartService(pServiceThreadData->pService, NULL));
+    *ReplySize = sizeof(DWORD);
+}
+
+
+VOID FASTCALL
+ScmHandleStartServiceRequest(
+    PSERVICE_THREAD_DATA pServiceThreadData,
+    PSCM_SERVICE_REQUEST Request,
+    DWORD RequestSize,
+    PSCM_SERVICE_REPLY Reply,
+    LPDWORD ReplySize)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    HANDLE KeyHandle;
+
+    InitializeObjectAttributes(
+       &ObjectAttributes,
+       &pServiceThreadData->pService->RegistryPath,
+       OBJ_CASE_INSENSITIVE,
+       NULL,
+       NULL);
+                                                         
+    Status = ZwOpenKey(
+       &KeyHandle,
+       KEY_READ,
+       &ObjectAttributes);
+
+    if (NT_SUCCESS(Status))
+    {
+       Status = ZwDeleteKey(KeyHandle);
+       if (NT_SUCCESS(Status))
+       {
+          ZwClose(KeyHandle);
+          CHECKPOINT;
+          RemoveEntryList(&pServiceThreadData->pService->ServiceListEntry);
+       }
+    }
+    Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+    *ReplySize = sizeof(DWORD);
+}
+
+
+DWORD
+WINAPI
+ScmNamedPipeServiceThread(LPVOID Context)
+{
+    SCM_SERVICE_REQUEST Request;
+    SCM_SERVICE_REPLY Reply;
+    DWORD cbBytesRead;
+    DWORD cbWritten, cbReplyBytes;
+    BOOL fSuccess;
+    PSERVICE_THREAD_DATA pServiceThreadData = Context;
+
+    ConnectNamedPipe(pServiceThreadData->hPipe, NULL);
+
+    for (;;)
+    {
+        fSuccess = ReadFile(
+            pServiceThreadData->hPipe,
+            &Request,
+            sizeof(Request),
+            &cbBytesRead,
+            NULL);
+
+        if (!fSuccess || cbBytesRead == 0)
+        {
+            break;
+        }
+
+        switch (Request.RequestCode)
+        {
+            case SCM_DELETESERVICE:
+                ScmHandleDeleteServiceRequest(
+                    pServiceThreadData,
+                    &Request,
+                    cbBytesRead,
+                    &Reply,
+                    &cbReplyBytes);
+                break;
+
+            case SCM_STARTSERVICE:
+                ScmHandleStartServiceRequest(
+                    pServiceThreadData,
+                    &Request,
+                    cbBytesRead,
+                    &Reply,
+                    &cbReplyBytes);
+                break;
+        }
+
+        fSuccess = WriteFile(
+            pServiceThreadData->hPipe,
+            &Reply,
+            cbReplyBytes,
+            &cbWritten,
+            NULL);
+
+        if (!fSuccess || cbReplyBytes != cbWritten)
+        {
+            break;
+        }
+    }
+
+    FlushFileBuffers(pServiceThreadData->hPipe);
+    DisconnectNamedPipe(pServiceThreadData->hPipe);
+    CloseHandle(pServiceThreadData->hPipe);
+
+    return NO_ERROR;
+}
+
+
+VOID FASTCALL
+ScmCreateServiceThread(
+    HANDLE hSCMPipe,
+    PSCM_OPENSERVICE_REPLY Reply,
+    LPDWORD ReplySize,
+    PSERVICE Service)
+{
+    HANDLE hPipe, hThread;
+    DWORD dwThreadId;
+    PSERVICE_THREAD_DATA ServiceThreadData;
+
+    ServiceThreadData = HeapAlloc(
+        GetProcessHeap(),
+        0,
+        sizeof(SERVICE_THREAD_DATA));
+
+    if (ServiceThreadData == NULL)
+    {
+        Reply->ReplyStatus = ERROR_NO_SYSTEM_RESOURCES;
+        CHECKPOINT;
+        return;
+    }
+
+    swprintf(Reply->PipeName, L"\\\\.\\pipe\\SCM.%08X.%08X", hSCMPipe, Service);
+
+    hPipe = CreateNamedPipeW(
+        Reply->PipeName,
+        PIPE_ACCESS_DUPLEX,
+        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+        PIPE_UNLIMITED_INSTANCES,
+        sizeof(SCM_SERVICE_REQUEST),
+        sizeof(SCM_SERVICE_REPLY),
+        PIPE_TIMEOUT,
+        NULL);
+
+    if (hPipe == INVALID_HANDLE_VALUE)
+    {
+        Reply->ReplyStatus = ERROR_NO_SYSTEM_RESOURCES;
+        CHECKPOINT;
+        return;
+    }
+
+    ServiceThreadData->hPipe = hPipe;
+    ServiceThreadData->pService = Service;
+
+    hThread = CreateThread(
+        NULL,
+        0,
+        ScmNamedPipeServiceThread,
+        ServiceThreadData,
+        0,
+        &dwThreadId);
+
+    if (!hThread)
+    {
+        Reply->ReplyStatus = ERROR_NO_SYSTEM_RESOURCES;
+        CHECKPOINT;
+        CloseHandle(hPipe);
+        return;
+    }
+
+    Reply->ReplyStatus = NO_ERROR;
+    *ReplySize = sizeof(SCM_OPENSERVICE_REPLY);
+}
+
+
+VOID FASTCALL
+ScmHandleOpenServiceRequest(
+    HANDLE hPipe,
+    PSCM_REQUEST Request,
+    DWORD RequestSize,
+    PSCM_REPLY Reply,
+    LPDWORD ReplySize)
+{
+    PSERVICE Service;
+    UNICODE_STRING ServiceName;
+
+    DPRINT("OpenService\n");
+
+    if (RequestSize != sizeof(SCM_OPENSERVICE_REQUEST))
+    {
+        Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
+        return;
+    }
+
+    ServiceName.Length = Request->OpenService.ServiceName.Length;
+    ServiceName.Buffer = Request->OpenService.ServiceName.Buffer;
+    Service = ScmFindService(&ServiceName);
+    if (Service == NULL)
+    {
+        DPRINT("OpenService - Service not found\n");
+        Reply->ReplyStatus = ERROR_SERVICE_DOES_NOT_EXIST;
+        return;
+    }
+
+    DPRINT("OpenService - Service found\n");
+    ScmCreateServiceThread(
+        hPipe,
+        &Reply->OpenService,
+        ReplySize,
+        Service);
+}
+
+
+VOID FASTCALL
+ScmHandleCreateServiceRequest(
+    HANDLE hPipe,
+    PSCM_REQUEST Request,
+    DWORD RequestSize,
+    PSCM_REPLY Reply,
+    LPDWORD ReplySize)
+{
+    PSERVICE Service;
+    NTSTATUS Status;
+    UNICODE_STRING ServiceName;
+
+    DPRINT("CreateService - %S\n", Request->CreateService.ServiceName.Buffer);
+
+    if (RequestSize != sizeof(SCM_CREATESERVICE_REQUEST))
+    {
+        Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
+        return;
+    }
+
+    Status = RtlCheckRegistryKey(
+        RTL_REGISTRY_SERVICES,
+        Request->CreateService.ServiceName.Buffer);
+
+    if (NT_SUCCESS(Status))
+    {
+        DPRINT("CreateService - Already exists\n");
+        Reply->ReplyStatus = ERROR_SERVICE_EXISTS;
+        return;
+    }
+
+    Status = RtlCreateRegistryKey(
+        RTL_REGISTRY_SERVICES,
+        Request->CreateService.ServiceName.Buffer);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("CreateService - Can't create key (%x)\n", Status);
+        Reply->ReplyStatus = Status;
+        return;
+    }
+
+    Status = RtlWriteRegistryValue(
+        RTL_REGISTRY_SERVICES,
+        Request->CreateService.ServiceName.Buffer,
+        L"Type",
+        REG_DWORD,
+        &Request->CreateService.dwServiceType,
+        sizeof(DWORD));
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("CreateService - Error writing value\n");
+        Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+        return;
+    }
+
+    Status = RtlWriteRegistryValue(
+        RTL_REGISTRY_SERVICES,
+        Request->CreateService.ServiceName.Buffer,
+        L"Start",
+        REG_DWORD,
+        &Request->CreateService.dwStartType,
+        sizeof(DWORD));
+
+    if (!NT_SUCCESS(Status))
+    {
+        Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+        return;
+    }
+
+    Status = RtlWriteRegistryValue(
+        RTL_REGISTRY_SERVICES,
+        Request->CreateService.ServiceName.Buffer,
+        L"ErrorControl",
+        REG_DWORD,
+        &Request->CreateService.dwErrorControl,
+        sizeof(DWORD));
+
+    if (!NT_SUCCESS(Status))
+    {
+        Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+        return;
+    }
+
+    if (Request->CreateService.BinaryPathName.Length)
+    {
+        Status = RtlWriteRegistryValue(
+            RTL_REGISTRY_SERVICES,
+            Request->CreateService.ServiceName.Buffer,
+            L"ImagePath",
+            REG_SZ,
+            Request->CreateService.BinaryPathName.Buffer,
+            Request->CreateService.BinaryPathName.Length + sizeof(UNICODE_NULL));
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT("CreateService - Error writing value\n");
+            Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+            return;
+        }
+    }
+
+    if (Request->CreateService.LoadOrderGroup.Length)
+    {
+        Status = RtlWriteRegistryValue(
+            RTL_REGISTRY_SERVICES,
+            Request->CreateService.ServiceName.Buffer,
+            L"Group",
+            REG_SZ,
+            Request->CreateService.LoadOrderGroup.Buffer,
+            Request->CreateService.LoadOrderGroup.Length + sizeof(UNICODE_NULL));
+
+        if (!NT_SUCCESS(Status))
+        {
+            Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+            return;
+        }
+    }
+
+    if (Request->CreateService.Dependencies.Length)
+    {
+        Status = RtlWriteRegistryValue(
+            RTL_REGISTRY_SERVICES,
+            Request->CreateService.ServiceName.Buffer,
+            L"Dependencies",
+            REG_SZ,
+            Request->CreateService.Dependencies.Buffer,
+            Request->CreateService.Dependencies.Length + sizeof(UNICODE_NULL));
+
+        if (!NT_SUCCESS(Status))
+        {
+            Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+            return;
+        }
+    }
+
+    if (Request->CreateService.DisplayName.Length)
+    {
+        Status = RtlWriteRegistryValue(
+            RTL_REGISTRY_SERVICES,
+            Request->CreateService.ServiceName.Buffer,
+            L"DisplayName",
+            REG_SZ,
+            Request->CreateService.DisplayName.Buffer,
+            Request->CreateService.DisplayName.Length + sizeof(UNICODE_NULL));
+
+        if (!NT_SUCCESS(Status))
+        {
+            Reply->ReplyStatus = RtlNtStatusToDosError(Status);
+            return;
+        }
+    }
+
+    if (Request->CreateService.ServiceStartName.Length ||
+        Request->CreateService.Password.Length)
+    {
+        DPRINT1("Unimplemented case\n");
+    }
+
+    ServiceName.Length = Request->OpenService.ServiceName.Length;
+    ServiceName.Buffer = Request->OpenService.ServiceName.Buffer;
+    Service = ScmCreateServiceListEntry(&ServiceName);
+    if (Service == NULL)
+    {
+        DPRINT("CreateService - Error creating service list entry\n");
+        Reply->ReplyStatus = ERROR_NOT_ENOUGH_MEMORY;
+        return;
+    }
+
+    DPRINT("CreateService - Success\n");
+    ScmCreateServiceThread(
+        hPipe,
+        &Reply->OpenService,
+        ReplySize,
+        Service);
+}
+
+
 BOOL
 ScmNamedPipeHandleRequest(
-    PVOID Request,
+    HANDLE hPipe,
+    PSCM_REQUEST Request,
     DWORD RequestSize,
-    PVOID Reply,
+    PSCM_REPLY Reply,
     LPDWORD ReplySize)
 {
-    DbgPrint("SCM READ: %s\n", Request);
+    *ReplySize = sizeof(DWORD);
+
+    if (RequestSize < sizeof(DWORD))
+    {
+        Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
+        return TRUE;
+    }
 
-    *ReplySize = 0;
-    return FALSE;
+    DPRINT("RequestCode: %x\n", Request->RequestCode);
+
+    switch (Request->RequestCode)
+    {
+        case SCM_OPENSERVICE:
+            ScmHandleOpenServiceRequest(
+                hPipe,
+                Request,
+                RequestSize,
+                Reply,
+                ReplySize);
+            break;
+
+        case SCM_CREATESERVICE:
+            ScmHandleCreateServiceRequest(
+                hPipe,
+                Request,
+                RequestSize,
+                Reply,
+                ReplySize);
+            break;
+
+        default:
+            Reply->ReplyStatus = ERROR_INVALID_PARAMETER;
+    }
+
+    return TRUE;
 }
 
 
@@ -109,8 +555,8 @@ DWORD
 WINAPI
 ScmNamedPipeThread(LPVOID Context)
 {
-    CHAR chRequest[PIPE_BUFSIZE];
-    CHAR chReply[PIPE_BUFSIZE];
+    SCM_REQUEST Request;
+    SCM_REPLY Reply;
     DWORD cbReplyBytes;
     DWORD cbBytesRead;
     DWORD cbWritten;
@@ -123,16 +569,16 @@ ScmNamedPipeThread(LPVOID Context)
     
     for (;;) {
         fSuccess = ReadFile(hPipe,
-                            &chRequest,
-                            PIPE_BUFSIZE,
+                            &Request,
+                            sizeof(Request),
                             &cbBytesRead,
                             NULL);
         if (!fSuccess || cbBytesRead == 0) {
             break;
         }
-        if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes)) {
+        if (ScmNamedPipeHandleRequest(hPipe, &Request, cbBytesRead, &Reply, &cbReplyBytes)) {
             fSuccess = WriteFile(hPipe,
-                                 &chReply,
+                                 &Reply,
                                  cbReplyBytes,
                                  &cbWritten,
                                  NULL);
@@ -162,8 +608,8 @@ BOOL ScmCreateNamedPipe(VOID)
               PIPE_ACCESS_DUPLEX,
               PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
               PIPE_UNLIMITED_INSTANCES,
-              PIPE_BUFSIZE,
-              PIPE_BUFSIZE,
+              sizeof(SCM_REQUEST),
+              sizeof(SCM_REPLY),
               PIPE_TIMEOUT,
               NULL);
     if (hPipe == INVALID_HANDLE_VALUE) {
index 443ac04..d517787 100644 (file)
@@ -2,6 +2,34 @@
  * services.h
  */
 
+typedef struct _SERVICE_GROUP
+{
+  LIST_ENTRY GroupListEntry;
+  UNICODE_STRING GroupName;
+
+  BOOLEAN ServicesRunning;
+
+} SERVICE_GROUP, *PSERVICE_GROUP;
+
+typedef struct _SERVICE
+{
+  LIST_ENTRY ServiceListEntry;
+  UNICODE_STRING ServiceName;
+  UNICODE_STRING RegistryPath;
+  UNICODE_STRING ServiceGroup;
+
+  ULONG Start;
+  ULONG Type;
+  ULONG ErrorControl;
+  ULONG Tag;
+
+  BOOLEAN ServiceRunning;
+  BOOLEAN ServiceVisited;
+
+  HANDLE ControlPipeHandle;
+  ULONG ProcessId;
+  ULONG ThreadId;
+} SERVICE, *PSERVICE;
 
 /* services.c */
 
@@ -14,6 +42,12 @@ NTSTATUS ScmCreateServiceDataBase(VOID);
 VOID ScmGetBootAndSystemDriverState(VOID);
 VOID ScmAutoStartServices(VOID);
 
+PSERVICE FASTCALL
+ScmCreateServiceListEntry(PUNICODE_STRING ServiceName);
+PSERVICE FASTCALL
+ScmFindService(PUNICODE_STRING ServiceName);
+NTSTATUS FASTCALL
+ScmStartService(PSERVICE Service, PSERVICE_GROUP Group);
 
 /* EOF */