diff --git a/reactos/subsys/system/services/database.c b/reactos/subsys/system/services/database.c index 127eaccc408..8473509ca80 100644 --- a/reactos/subsys/system/services/database.c +++ b/reactos/subsys/system/services/database.c @@ -404,6 +404,32 @@ ScmReadGroupList(VOID) } +VOID +ScmDeleteMarkedServices(VOID) +{ + PLIST_ENTRY ServiceEntry; + PSERVICE CurrentService; + + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + ServiceEntry = ServiceEntry->Flink; + + if (CurrentService->bDeleted == TRUE) + { + DPRINT1("Delete service: %S\n", CurrentService->lpServiceName); + + /* FIXME: Delete the registry keys */ + + /* FIXME: Delete the service record from the list */ + + } + } +} + + DWORD ScmCreateServiceDatabase(VOID) { @@ -474,7 +500,8 @@ ScmCreateServiceDatabase(VOID) RegCloseKey(hServicesKey); - /* FIXME: Delete services that are marked for delete */ + /* Delete services that are marked for delete */ + ScmDeleteMarkedServices(); DPRINT("ScmCreateServiceDatabase() done\n"); @@ -836,8 +863,6 @@ static NTSTATUS ScmStartService(PSERVICE Service, PSERVICE_GROUP Group) { - WCHAR szDriverPath[MAX_PATH]; - UNICODE_STRING DriverPath; NTSTATUS Status; DPRINT("ScmStartService() called\n"); @@ -845,21 +870,12 @@ ScmStartService(PSERVICE Service, Service->ControlPipeHandle = INVALID_HANDLE_VALUE; DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType); - if (Service->Status.dwServiceType == SERVICE_KERNEL_DRIVER || - Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER || - Service->Status.dwServiceType == SERVICE_RECOGNIZER_DRIVER) + if (Service->Status.dwServiceType & SERVICE_DRIVER) { /* Load driver */ - wcscpy(szDriverPath, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - wcscat(szDriverPath, - Service->lpServiceName); - - RtlInitUnicodeString(&DriverPath, - szDriverPath); - - DPRINT(" Path: %wZ\n", &DriverPath); - Status = NtLoadDriver(&DriverPath); + Status = ScmLoadDriver(Service); + if (Status == STATUS_SUCCESS) + Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP; } else { diff --git a/reactos/subsys/system/services/driver.c b/reactos/subsys/system/services/driver.c new file mode 100644 index 00000000000..24c634b60b9 --- /dev/null +++ b/reactos/subsys/system/services/driver.c @@ -0,0 +1,113 @@ +/* + * driver.c + */ + +/* INCLUDES *****************************************************************/ + +#include "services.h" + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +ScmLoadDriver(PSERVICE lpService) +{ + WCHAR szDriverPath[MAX_PATH]; + UNICODE_STRING DriverPath; + NTSTATUS Status; + + /* Build the driver path */ + wcscpy(szDriverPath, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + wcscat(szDriverPath, + lpService->lpServiceName); + + RtlInitUnicodeString(&DriverPath, + szDriverPath); + + /* FIXME: Acquire privilege */ + + DPRINT(" Path: %wZ\n", &DriverPath); + Status = NtLoadDriver(&DriverPath); + + /* FIXME: Release privilege */ + + return Status; +} + + +DWORD +ScmUnloadDriver(PSERVICE lpService) +{ + WCHAR szDriverPath[MAX_PATH]; + UNICODE_STRING DriverPath; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + + /* Build the driver path */ + wcscpy(szDriverPath, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + wcscat(szDriverPath, + lpService->lpServiceName); + + RtlInitUnicodeString(&DriverPath, + szDriverPath); + + /* FIXME: Acquire privilege */ + + Status = NtUnloadDriver(&DriverPath); + + /* FIXME: Release privilege */ + + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + } + + return dwError; +} + + +DWORD +ScmControlDriver(PSERVICE lpService, + DWORD dwControl, + LPSERVICE_STATUS lpServiceStatus) +{ + DWORD dwError; + + DPRINT("ScmControlDriver() called\n"); + + switch (dwControl) + { + case SERVICE_CONTROL_STOP: + if (lpService->Status.dwCurrentState != SERVICE_RUNNING) + { + dwError = ERROR_INVALID_SERVICE_CONTROL; + goto done; + } + + dwError = ScmUnloadDriver(lpService); + if (dwError == ERROR_SUCCESS) + { + lpService->Status.dwControlsAccepted = 0; + lpService->Status.dwCurrentState = SERVICE_STOPPED; + } + break; + + case SERVICE_CONTROL_INTERROGATE: + dwError = ERROR_INVALID_SERVICE_CONTROL; + break; + + default: + dwError = ERROR_INVALID_SERVICE_CONTROL; + } + +done:; + DPRINT("ScmControlDriver() done (Erorr: %lu)\n", dwError); + + return dwError; +} + +/* EOF */ diff --git a/reactos/subsys/system/services/rpcserver.c b/reactos/subsys/system/services/rpcserver.c index 92039e61096..35edd556aef 100644 --- a/reactos/subsys/system/services/rpcserver.c +++ b/reactos/subsys/system/services/rpcserver.c @@ -281,6 +281,7 @@ ScmrControlService(handle_t BindingHandle, PSERVICE_HANDLE hSvc; PSERVICE lpService; ACCESS_MASK DesiredAccess; + DWORD dwError = ERROR_SUCCESS; DPRINT("ScmrControlService() called\n"); @@ -335,16 +336,30 @@ ScmrControlService(handle_t BindingHandle, return ERROR_INVALID_HANDLE; } - - /* FIXME: Send control code to the service */ - + if (lpService->Status.dwServiceType & SERVICE_DRIVER) + { + /* Send control code to the driver */ + dwError = ScmControlDriver(lpService, + dwControl, + lpServiceStatus); + } + else + { + /* FIXME: Send control code to the service */ +#if 0 + dwError = ScmControlService(lpService, + dwControl, + lpServiceStatus); +#endif + dwError = ERROR_INVALID_SERVICE_CONTROL; + } /* Return service status information */ RtlCopyMemory(lpServiceStatus, &lpService->Status, sizeof(SERVICE_STATUS)); - return ERROR_SUCCESS; + return dwError; } diff --git a/reactos/subsys/system/services/services.h b/reactos/subsys/system/services/services.h index ce316c31cc1..997ec6a6a26 100644 --- a/reactos/subsys/system/services/services.h +++ b/reactos/subsys/system/services/services.h @@ -76,6 +76,15 @@ DWORD ScmCreateNewServiceRecord(LPWSTR lpServiceName, DWORD ScmMarkServiceForDelete(PSERVICE pService); +/* driver.c */ + +NTSTATUS ScmLoadDriver(PSERVICE lpService); +DWORD ScmUnloadDriver(PSERVICE lpService); +DWORD ScmControlDriver(PSERVICE lpService, + DWORD dwControl, + LPSERVICE_STATUS lpServiceStatus); + + /* rpcserver.c */ VOID ScmStartRpcServer(VOID); diff --git a/reactos/subsys/system/services/services.xml b/reactos/subsys/system/services/services.xml index ac9ae45ee6e..d8f3409d24f 100644 --- a/reactos/subsys/system/services/services.xml +++ b/reactos/subsys/system/services/services.xml @@ -12,6 +12,7 @@ rpcrt4 config.c database.c + driver.c rpcserver.c services.c services.rc