/*
- *
- * service control manager
- *
- * ReactOS Operating System
- *
- * --------------------------------------------------------------------
- *
- * 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.
+ * PROJECT: ReactOS Service Control Manager
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/system/services/database.c
+ * PURPOSE: Database control interface
+ * COPYRIGHT: Copyright 2002-2006 Eric Kohl
+ * Copyright 2006 Hervé Poussineau <hpoussin@reactos.org>
+ * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
+ * Gregor Brunmar <gregor.brunmar@home.se>
*
*/
/* FUNCTIONS *****************************************************************/
+
PSERVICE
ScmGetServiceEntryByName(LPWSTR lpServiceName)
{
}
+PSERVICE
+ScmGetServiceEntryByClientHandle(ULONG Handle)
+{
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+
+ DPRINT("ScmGetServiceEntryByClientHandle() called\n");
+ DPRINT("looking for %lu\n", Handle);
+
+ ServiceEntry = ServiceListHead.Flink;
+ while (ServiceEntry != &ServiceListHead)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ if (CurrentService->hClient == Handle)
+ {
+ DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName);
+ return CurrentService;
+ }
+
+ ServiceEntry = ServiceEntry->Flink;
+ }
+
+ DPRINT("Couldn't find a matching service\n");
+
+ return NULL;
+}
+
+
DWORD
ScmCreateNewServiceRecord(LPWSTR lpServiceName,
PSERVICE *lpServiceRecord)
DPRINT("Service: '%S'\n", lpServiceName);
/* Allocate service entry */
- lpService = HeapAlloc(GetProcessHeap(),
+ lpService = (SERVICE*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SERVICE) + ((wcslen(lpServiceName) + 1) * sizeof(WCHAR)));
if (lpService == NULL)
}
DPRINT("ServiceName: '%S'\n", lpService->lpServiceName);
- DPRINT("Group: '%S'\n", lpService->lpGroup->lpGroupName);
+ if (lpService->lpGroup != NULL)
+ {
+ DPRINT("Group: '%S'\n", lpService->lpGroup->lpGroupName);
+ }
DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
lpService->dwStartType,
lpService->Status.dwServiceType,
}
+VOID
+ScmShutdownServiceDatabase(VOID)
+{
+ DPRINT("ScmShutdownServiceDatabase() called\n");
+
+ ScmDeleteMarkedServices();
+ RtlDeleteResource(&DatabaseLock);
+
+ DPRINT("ScmShutdownServiceDatabase() done\n");
+}
+
+
static NTSTATUS
ScmCheckDriver(PSERVICE Service)
{
BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) +
2 * MAX_PATH * sizeof(WCHAR);
- DirInfo = HeapAlloc(GetProcessHeap(),
+ DirInfo = (OBJECT_DIRECTORY_INFORMATION*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
BufferLength);
}
+DWORD
+ScmControlService(PSERVICE Service,
+ DWORD dwControl,
+ LPSERVICE_STATUS lpServiceStatus)
+{
+ PSCM_CONTROL_PACKET ControlPacket;
+ DWORD Count;
+ DWORD TotalLength;
+
+ DPRINT("ScmControlService() called\n");
+
+ TotalLength = wcslen(Service->lpServiceName) + 1;
+
+ ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)));
+ if (ControlPacket == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ ControlPacket->dwControl = dwControl;
+ ControlPacket->hClient = Service->hClient;
+ ControlPacket->dwSize = TotalLength;
+ wcscpy(&ControlPacket->szArguments[0], Service->lpServiceName);
+
+ /* Send the start command */
+ WriteFile(Service->ControlPipeHandle,
+ ControlPacket,
+ sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)),
+ &Count,
+ NULL);
+
+ /* FIXME: Read the reply */
+
+ /* Release the contol packet */
+ HeapFree(GetProcessHeap(),
+ 0,
+ ControlPacket);
+
+ RtlCopyMemory(lpServiceStatus,
+ &Service->Status,
+ sizeof(SERVICE_STATUS));
+
+ DPRINT("ScmControlService) done\n");
+
+ return ERROR_SUCCESS;
+}
+
+
static DWORD
ScmSendStartCommand(PSERVICE Service,
LPWSTR Arguments)
{
- PSCM_START_PACKET StartPacket;
+ PSCM_CONTROL_PACKET ControlPacket;
DWORD TotalLength;
DWORD ArgsLength = 0;
DWORD Length;
}
}
TotalLength++;
- DPRINT("ArgsLength: %ld\nTotalLength: %ld\n\n", ArgsLength, TotalLength);
+ DPRINT("ArgsLength: %ld TotalLength: %ld\n", ArgsLength, TotalLength);
- /* Allocate start command packet */
- StartPacket = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof(SCM_START_PACKET) + (TotalLength - 1) * sizeof(WCHAR));
- if (StartPacket == NULL)
+ /* Allocate a control packet */
+ ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR));
+ if (ControlPacket == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
- StartPacket->Command = SCM_START_COMMAND;
- StartPacket->Size = TotalLength;
- Ptr = &StartPacket->Arguments[0];
+ ControlPacket->dwControl = SERVICE_CONTROL_START;
+ ControlPacket->hClient = Service->hClient;
+ ControlPacket->dwSize = TotalLength;
+ Ptr = &ControlPacket->szArguments[0];
wcscpy(Ptr, Service->lpServiceName);
Ptr += (wcslen(Service->lpServiceName) + 1);
/* Send the start command */
WriteFile(Service->ControlPipeHandle,
- StartPacket,
- sizeof(SCM_START_PACKET) + (TotalLength - 1) * sizeof(WCHAR),
+ ControlPacket,
+ sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR),
&Count,
NULL);
/* FIXME: Read the reply */
- /* Release the start command packet */
+ /* Release the contol packet */
HeapFree(GetProcessHeap(),
0,
- StartPacket);
+ ControlPacket);
DPRINT("ScmSendStartCommand() done\n");
STARTUPINFOW StartupInfo;
UNICODE_STRING ImagePath;
ULONG Type;
+ DWORD ServiceCurrent = 0;
BOOL Result;
NTSTATUS Status;
DWORD dwError = ERROR_SUCCESS;
+ WCHAR NtControlPipeName[MAX_PATH + 1];
RtlInitUnicodeString(&ImagePath, NULL);
DPRINT("ImagePath: '%S'\n", ImagePath.Buffer);
DPRINT("Type: %lx\n", Type);
- /* Create '\\.\pipe\net\NtControlPipe' instance */
- Service->ControlPipeHandle = CreateNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe",
+ /* Get the service number */
+ RtlZeroMemory(&QueryTable,
+ sizeof(QueryTable));
+
+ QueryTable[0].Name = L"";
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].EntryContext = &ServiceCurrent;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+ L"ServiceCurrent",
+ QueryTable,
+ NULL,
+ NULL);
+
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ /* TODO: Create registry entry with correct write access */
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+ return RtlNtStatusToDosError(Status);
+ }
+ else
+ {
+ ServiceCurrent++;
+ }
+
+ Status = RtlWriteRegistryValue(RTL_REGISTRY_CONTROL, L"ServiceCurrent", L"", REG_DWORD, &ServiceCurrent, sizeof(ServiceCurrent));
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
+ return RtlNtStatusToDosError(Status);
+ }
+
+ /* Create '\\.\pipe\net\NtControlPipeXXX' instance */
+ swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", ServiceCurrent);
+ Service->ControlPipeHandle = CreateNamedPipeW(NtControlPipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
100,
4,
30000,
NULL);
- DPRINT("CreateNamedPipeW() done\n");
+ DPRINT1("CreateNamedPipeW(%S) done\n", NtControlPipeName);
if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE)
{
- DPRINT1("Failed to create control pipe!\n");
+ DPRINT("Failed to create control pipe!\n");
return GetLastError();
}
ResumeThread(ProcessInformation.hThread);
/* Connect control pipe */
- if (ConnectNamedPipe(Service->ControlPipeHandle, NULL))
+ if (ConnectNamedPipe(Service->ControlPipeHandle, NULL) ?
+ TRUE : (dwError = GetLastError()) == ERROR_PIPE_CONNECTED)
{
- DWORD dwProcessId = 0;
DWORD dwRead = 0;
DPRINT("Control pipe connected!\n");
- /* Read thread id from pipe */
+ /* Read SERVICE_STATUS_HANDLE from pipe */
if (!ReadFile(Service->ControlPipeHandle,
- (LPVOID)&dwProcessId,
+ (LPVOID)&Service->hClient,
sizeof(DWORD),
&dwRead,
NULL))
}
else
{
- DPRINT("Received process id %lu\n", dwProcessId);
+ DPRINT("Received service status %lu\n", Service->hClient);
/* Send start command */
dwError = ScmSendStartCommand(Service, lpArgs);
}
else
{
- dwError = GetLastError();
- DPRINT("Connecting control pipe failed!\n");
+ DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError);
/* Close control pipe */
CloseHandle(Service->ControlPipeHandle);
}
}
+
+VOID
+ScmAutoShutdownServices(VOID)
+{
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+ SERVICE_STATUS ServiceStatus;
+
+ DPRINT("ScmAutoShutdownServices() called\n");
+
+ ServiceEntry = ServiceListHead.Flink;
+ while (ServiceEntry != &ServiceListHead)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
+
+ if (CurrentService->Status.dwCurrentState == SERVICE_RUNNING ||
+ CurrentService->Status.dwCurrentState == SERVICE_START_PENDING)
+ {
+ /* shutdown service */
+ ScmControlService(CurrentService, SERVICE_CONTROL_STOP, &ServiceStatus);
+ }
+
+ ServiceEntry = ServiceEntry->Flink;
+ }
+
+ DPRINT("ScmGetBootAndSystemDriverState() done\n");
+}
+
/* EOF */