- Rewrote the code that reads the service configuration from the registry because it was not flexible enough with respect to the handling of default values. - Read delete flag from the registry. Modified: trunk/reactos/subsys/system/services/config.c Modified: trunk/reactos/subsys/system/services/database.c Modified: trunk/reactos/subsys/system/services/rpcserver.c Modified: trunk/reactos/subsys/system/services/services.c Modified: trunk/reactos/subsys/system/services/services.h _____
Modified: trunk/reactos/subsys/system/services/config.c --- trunk/reactos/subsys/system/services/config.c 2005-11-06 10:48:14 UTC (rev 19025) +++ trunk/reactos/subsys/system/services/config.c 2005-11-06 11:56:56 UTC (rev 19026) @@ -43,6 +43,51 @@
DWORD +ScmCreateServiceKey(LPWSTR lpServiceName, + REGSAM samDesired, + PHKEY phKey) +{ + HKEY hServicesKey = NULL; + DWORD dwDisposition; + DWORD dwError; + + *phKey = NULL; + + dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"System\CurrentControlSet\Services", + 0, + KEY_READ | KEY_CREATE_SUB_KEY, + &hServicesKey); + if (dwError != ERROR_SUCCESS) + return dwError; + + dwError = RegCreateKeyExW(hServicesKey, + lpServiceName, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + samDesired, + NULL, + phKey, + &dwDisposition); +#if 0 + if ((dwError == ERROR_SUCCESS) && + (dwDisposition == REG_OPENED_EXISTING_KEY)) + { + RegCloseKey(*phKey); + *phKey = NULL; + dwError = ERROR_SERVICE_EXISTS; + } +#endif + + RegCloseKey(hServicesKey); + + return dwError; +} + + + +DWORD ScmWriteDependencies(HKEY hServiceKey, LPWSTR lpDependencies, DWORD dwDependenciesLength) @@ -130,5 +175,106 @@ return dwError; }
+ +DWORD +ScmMarkServiceForDelete(PSERVICE pService) +{ + HKEY hServiceKey = NULL; + DWORD dwValue = 1; + DWORD dwError; + + DPRINT("ScmMarkServiceForDelete() called\n"); + + dwError = ScmOpenServiceKey(pService->lpServiceName, + KEY_WRITE, + &hServiceKey); + if (dwError != ERROR_SUCCESS) + return dwError; + + dwError = RegSetValueExW(hServiceKey, + L"DeleteFlag", + 0, + REG_DWORD, + (LPBYTE)&dwValue, + sizeof(DWORD)); + + RegCloseKey(hServiceKey); + + return dwError; +} + + +BOOL +ScmIsDeleteFlagSet(HKEY hServiceKey) +{ + DWORD dwError; + DWORD dwType; + DWORD dwFlag; + DWORD dwSize = sizeof(DWORD); + + dwError = RegQueryValueExW(hServiceKey, + L"DeleteFlag", + 0, + &dwType, + (LPBYTE)&dwFlag, + &dwSize); + + return (dwError == ERROR_SUCCESS); +} + + +DWORD +ScmReadString(HKEY hServiceKey, + LPWSTR lpValueName, + LPWSTR *lpValue) +{ + DWORD dwError; + DWORD dwSize; + DWORD dwType; + LPBYTE ptr = NULL; + + *lpValue = NULL; + + dwSize = 0; + dwError = RegQueryValueExW(hServiceKey, + lpValueName, + 0, + &dwType, + NULL, + &dwSize); + if (dwError != ERROR_SUCCESS) + return dwError; + + ptr = HeapAlloc(GetProcessHeap(), 0, dwSize); + if (ptr == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + dwError = RegQueryValueExW(hServiceKey, + lpValueName, + 0, + &dwType, + ptr, + &dwSize); + if (dwError != ERROR_SUCCESS) + goto done; + + if (dwType == REG_EXPAND_SZ) + { + /* FIXME: ... */ + DPRINT1("Expand me!\n"); + *lpValue = (LPWSTR)ptr; + } + else + { + *lpValue = (LPWSTR)ptr; + } + +done:; + if (dwError != ERROR_SUCCESS) + HeapFree(GetProcessHeap(), 0, ptr); + + return dwError; +} + /* EOF */
_____
Modified: trunk/reactos/subsys/system/services/database.c --- trunk/reactos/subsys/system/services/database.c 2005-11-06 10:48:14 UTC (rev 19025) +++ trunk/reactos/subsys/system/services/database.c 2005-11-06 11:56:56 UTC (rev 19026) @@ -211,89 +211,6 @@
}
-static NTSTATUS STDCALL -CreateServiceListEntry(LPWSTR lpServiceName) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[6]; - PSERVICE Service = NULL; - NTSTATUS Status; - - DPRINT("Service: '%S'\n", lpServiceName); - - - /* Allocate service entry */ - Service = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - sizeof(SERVICE) + ((wcslen(lpServiceName) + 1) * sizeof(WCHAR))); - if (Service == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Copy service name */ - wcscpy(Service->szServiceName, lpServiceName); - Service->lpServiceName = Service->szServiceName; - Service->lpDisplayName = Service->lpServiceName; - - /* Get service data */ - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"Start"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].EntryContext = &Service->dwStartType; - - QueryTable[1].Name = L"Type"; - QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[1].EntryContext = &Service->Status.dwServiceType; - - QueryTable[2].Name = L"ErrorControl"; - QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[2].EntryContext = &Service->dwErrorControl; - - QueryTable[3].Name = L"Group"; - QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[3].EntryContext = &Service->ServiceGroup; - - QueryTable[4].Name = L"Tag"; - QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[4].EntryContext = &Service->dwTag; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - lpServiceName, - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status)) - { - PrintString("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - HeapFree(GetProcessHeap(), 0, Service); - return Status; - } - - DPRINT("ServiceName: '%S'\n", Service->lpServiceName); - DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); - DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n", - Service->dwStartType, - Service->Status.dwServiceType, - Service->dwTag, - Service->dwErrorControl); - - /* Append service entry */ - InsertTailList(&ServiceListHead, - &Service->ServiceListEntry); - - Service->Status.dwCurrentState = SERVICE_STOPPED; - Service->Status.dwControlsAccepted = 0; - Service->Status.dwWin32ExitCode = 0; - Service->Status.dwServiceSpecificExitCode = 0; - Service->Status.dwCheckPoint = 0; - Service->Status.dwWaitHint = 2000; /* 2 seconds */ - - return STATUS_SUCCESS; -} - - DWORD ScmCreateNewServiceRecord(LPWSTR lpServiceName, PSERVICE *lpServiceRecord) @@ -331,31 +248,127 @@ }
-NTSTATUS -ScmCreateServiceDataBase(VOID) +static DWORD +CreateServiceListEntry(LPWSTR lpServiceName, + HKEY hServiceKey) { - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING ServicesKeyName = - RTL_CONSTANT_STRING(L"\Registry\Machine\System\CurrentControlSet\Se rvices"); - UNICODE_STRING SubKeyName; - HKEY ServicesKey; - ULONG Index; - NTSTATUS Status; + PSERVICE lpService = NULL; + LPWSTR lpGroup = NULL; + DWORD dwSize; + DWORD dwError; + DWORD dwServiceType; + DWORD dwStartType; + DWORD dwErrorControl; + DWORD dwTagId;
- PKEY_BASIC_INFORMATION KeyInfo = NULL; - ULONG KeyInfoLength = 0; - ULONG ReturnedLength; + DPRINT("Service: '%S'\n", lpServiceName); + if (*lpServiceName == L'{') + return ERROR_SUCCESS;
- DPRINT("ScmCreateServiceDataBase() called\n"); + dwSize = sizeof(DWORD); + dwError = RegQueryValueExW(hServiceKey, + L"Type", + NULL, + NULL, + (LPBYTE)&dwServiceType, + &dwSize); + if (dwError != ERROR_SUCCESS) + return ERROR_SUCCESS;
- /* Initialize basic variables */ - InitializeListHead(&GroupListHead); - InitializeListHead(&ServiceListHead); + if (((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) && + ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS) && + (dwServiceType != SERVICE_KERNEL_DRIVER) && + (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)) + return ERROR_SUCCESS;
- /* Initialize the database lock */ - RtlInitializeResource(&DatabaseLock); + DPRINT("Service type: %lx\n", dwServiceType);
+ dwSize = sizeof(DWORD); + dwError = RegQueryValueExW(hServiceKey, + L"Start", + NULL, + NULL, + (LPBYTE)&dwStartType, + &dwSize); + if (dwError != ERROR_SUCCESS) + return ERROR_SUCCESS; + + DPRINT("Start type: %lx\n", dwStartType); + + dwSize = sizeof(DWORD); + dwError = RegQueryValueExW(hServiceKey, + L"ErrorControl", + NULL, + NULL, + (LPBYTE)&dwErrorControl, + &dwSize); + if (dwError != ERROR_SUCCESS) + return ERROR_SUCCESS; + + DPRINT("Error control: %lx\n", dwErrorControl); + + dwError = RegQueryValueExW(hServiceKey, + L"Tag", + NULL, + NULL, + (LPBYTE)&dwTagId, + &dwSize); + if (dwError != ERROR_SUCCESS) + dwTagId = 0; + + DPRINT("Tag: %lx\n", dwTagId); + + dwError = ScmReadString(hServiceKey, + L"Group", + &lpGroup); + if (dwError != ERROR_SUCCESS) + lpGroup = NULL; + + DPRINT("Group: %S\n", lpGroup); + + dwError = ScmCreateNewServiceRecord(lpServiceName, + &lpService); + if (dwError != ERROR_SUCCESS) + goto done; + + lpService->Status.dwServiceType = dwServiceType; + lpService->dwStartType = dwStartType; + lpService->dwErrorControl = dwErrorControl; + lpService->dwTag = dwTagId; + + if (lpGroup != NULL) + { + lpService->lpServiceGroup = lpGroup; + lpGroup = NULL; + } + + DPRINT("ServiceName: '%S'\n", lpService->lpServiceName); + DPRINT("Group: '%S'\n", lpService->lpServiceGroup); + DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n", + lpService->dwStartType, + lpService->Status.dwServiceType, + lpService->dwTag, + lpService->dwErrorControl); + + if (ScmIsDeleteFlagSet(hServiceKey)) + lpService->bDeleted = TRUE; + +done:; + if (lpGroup != NULL) + HeapFree(GetProcessHeap(), 0, lpGroup); + + return dwError; +} + + +DWORD +ScmReadGroupList(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + InitializeListHead(&GroupListHead); + /* Build group order list */ RtlZeroMemory(&QueryTable, sizeof(QueryTable)); @@ -368,75 +381,84 @@ QueryTable, NULL, NULL); - if (!NT_SUCCESS(Status)) - return Status;
- RtlInitUnicodeString(&ServicesKeyName, - L"\Registry\Machine\System\CurrentControlSet\Services"); + return RtlNtStatusToDosError(Status); +}
- InitializeObjectAttributes(&ObjectAttributes, - &ServicesKeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL);
- Status = RtlpNtOpenKey(&ServicesKey, - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, - &ObjectAttributes, - 0); - if (!NT_SUCCESS(Status)) - return Status; +DWORD +ScmCreateServiceDatabase(VOID) +{ + WCHAR szSubKey[MAX_PATH]; + HKEY hServicesKey; + HKEY hServiceKey; + DWORD dwSubKey; + DWORD dwSubKeyLength; + FILETIME ftLastChanged; + DWORD dwError;
- /* Allocate key info buffer */ - KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR); - KeyInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, KeyInfoLength); - if (KeyInfo == NULL) - { - NtClose(ServicesKey); - return STATUS_INSUFFICIENT_RESOURCES; - } + DPRINT("ScmCreateServiceDatabase() called\n");
- Index = 0; - while (TRUE) + dwError = ScmReadGroupList(); + if (dwError != ERROR_SUCCESS) + return dwError; + + /* Initialize basic variables */ + InitializeListHead(&ServiceListHead); + + /* Initialize the database lock */ + RtlInitializeResource(&DatabaseLock); + + dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"System\CurrentControlSet\Services", + 0, + KEY_READ, + &hServicesKey); + if (dwError != ERROR_SUCCESS) + return dwError; + + dwSubKey = 0; + for (;;) { - Status = NtEnumerateKey(ServicesKey, - Index, - KeyBasicInformation, - KeyInfo, - KeyInfoLength, - &ReturnedLength); - if (NT_SUCCESS(Status)) + dwSubKeyLength = MAX_PATH; + dwError = RegEnumKeyExW(hServicesKey, + dwSubKey, + szSubKey, + &dwSubKeyLength, + NULL, + NULL, + NULL, + &ftLastChanged); + if (dwError == ERROR_SUCCESS && + szSubKey[0] != L'{') { - if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR)) + DPRINT("SubKeyName: '%S'\n", szSubKey); + + dwError = RegOpenKeyExW(hServicesKey, + szSubKey, + 0, + KEY_READ, + &hServiceKey); + if (dwError == ERROR_SUCCESS) { - SubKeyName.Length = KeyInfo->NameLength; - SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR); - SubKeyName.Buffer = KeyInfo->Name; - SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0; + dwError = CreateServiceListEntry(szSubKey, + hServiceKey);
- DPRINT("KeyName: '%wZ'\n", &SubKeyName); - Status = CreateServiceListEntry(SubKeyName.Buffer); - - /* Ignore services without proper registry. */ - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - { - Status = STATUS_SUCCESS; - } + RegCloseKey(hServiceKey); } }
- if (!NT_SUCCESS(Status)) + if (dwError != ERROR_SUCCESS) break;
- Index++; + dwSubKey++; }
- HeapFree(GetProcessHeap(), 0, KeyInfo); - NtClose(ServicesKey); + RegCloseKey(hServicesKey);
- DPRINT("ScmCreateServiceDataBase() done\n"); + DPRINT("ScmCreateServiceDatabase() done\n");
- return STATUS_SUCCESS; + return ERROR_SUCCESS; }
@@ -518,7 +540,7 @@ Service->Status.dwCurrentState = SERVICE_RUNNING;
/* Find the driver's group and mark it as 'running' */ - if (Service->ServiceGroup.Buffer != NULL) + if (Service->lpServiceGroup != NULL) { GroupEntry = GroupListHead.Flink; while (GroupEntry != &GroupListHead) @@ -526,7 +548,8 @@ CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
DPRINT("Checking group '%wZ'\n", &CurrentGroup->GroupName); - if (RtlEqualUnicodeString(&Service->ServiceGroup, &CurrentGroup->GroupName, TRUE)) + if (Service->lpServiceGroup != NULL && + _wcsicmp(Service->lpServiceGroup, CurrentGroup->GroupName.Buffer) == 0) { CurrentGroup->ServicesRunning = TRUE; } @@ -902,7 +925,8 @@ { CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
- if ((RtlEqualUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE)) && + if ((CurrentService->lpServiceGroup != NULL) && + (_wcsicmp(CurrentGroup->GroupName.Buffer, CurrentService->lpServiceGroup) == 0) && (CurrentService->dwStartType == SERVICE_AUTO_START) && (CurrentService->ServiceVisited == FALSE) && (CurrentService->dwTag == CurrentGroup->TagArray[i])) @@ -922,7 +946,8 @@ { CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
- if ((RtlEqualUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE)) && + if ((CurrentService->lpServiceGroup != NULL) && + (_wcsicmp(CurrentGroup->GroupName.Buffer, CurrentService->lpServiceGroup) == 0) && (CurrentService->dwStartType == SERVICE_AUTO_START) && (CurrentService->ServiceVisited == FALSE)) { @@ -943,7 +968,7 @@ { CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
- if ((CurrentService->ServiceGroup.Length != 0) && + if ((CurrentService->lpServiceGroup != NULL) && (CurrentService->dwStartType == SERVICE_AUTO_START) && (CurrentService->ServiceVisited == FALSE)) { @@ -961,7 +986,7 @@ { CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
- if ((CurrentService->ServiceGroup.Length == 0) && + if ((CurrentService->lpServiceGroup == NULL) && (CurrentService->dwStartType == SERVICE_AUTO_START) && (CurrentService->ServiceVisited == FALSE)) { @@ -983,32 +1008,4 @@ } }
- -DWORD -ScmMarkServiceForDelete(PSERVICE pService) -{ - HKEY hServiceKey = NULL; - DWORD dwValue = 1; - DWORD dwError; - - DPRINT("ScmMarkServiceForDelete() called\n"); - - dwError = ScmOpenServiceKey(pService->lpServiceName, - KEY_WRITE, - &hServiceKey); - if (dwError != ERROR_SUCCESS) - return dwError; - - dwError = RegSetValueExW(hServiceKey, - L"DeleteFlag", - 0, - REG_DWORD, - (LPBYTE)&dwValue, - sizeof(DWORD)); - - RegCloseKey(hServiceKey); - - return dwError; -} - /* EOF */ _____
Modified: trunk/reactos/subsys/system/services/rpcserver.c --- trunk/reactos/subsys/system/services/rpcserver.c 2005-11-06 10:48:14 UTC (rev 19025) +++ trunk/reactos/subsys/system/services/rpcserver.c 2005-11-06 11:56:56 UTC (rev 19026) @@ -560,49 +560,6 @@
}
-static DWORD -CreateServiceKey(LPWSTR lpServiceName, - PHKEY phKey) -{ - HKEY hServicesKey = NULL; - DWORD dwDisposition; - DWORD dwError; - - *phKey = NULL; - - dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"System\CurrentControlSet\Services", - 0, - KEY_WRITE, - &hServicesKey); - if (dwError != ERROR_SUCCESS) - return dwError; - - dwError = RegCreateKeyExW(hServicesKey, - lpServiceName, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_WRITE, - NULL, - phKey, - &dwDisposition); -#if 0 - if ((dwError == ERROR_SUCCESS) && - (dwDisposition == REG_OPENED_EXISTING_KEY)) - { - RegCloseKey(*phKey); - *phKey = NULL; - dwError = ERROR_SERVICE_EXISTS; - } -#endif - - RegCloseKey(hServicesKey); - - return dwError; -} - - /* Function 12 */ unsigned long ScmrCreateServiceW(handle_t BindingHandle, @@ -710,7 +667,9 @@
/* Write service data to the registry */ /* Create the service key */ - dwError = CreateServiceKey(lpServiceName, &hServiceKey); + dwError = ScmCreateServiceKey(lpServiceName, + KEY_WRITE, + &hServiceKey); if (dwError != ERROR_SUCCESS) goto done;
_____
Modified: trunk/reactos/subsys/system/services/services.c --- trunk/reactos/subsys/system/services/services.c 2005-11-06 10:48:14 UTC (rev 19025) +++ trunk/reactos/subsys/system/services/services.c 2005-11-06 11:56:56 UTC (rev 19026) @@ -313,7 +313,7 @@
{ HANDLE hScmStartEvent; HANDLE hEvent; - NTSTATUS Status; + DWORD dwError;
DPRINT("SERVICES: Service Control Manager\n");
@@ -335,10 +335,10 @@
/* Create the service database */ - Status = ScmCreateServiceDataBase(); - if (!NT_SUCCESS(Status)) + dwError = ScmCreateServiceDatabase(); + if (dwError != ERROR_SUCCESS) { - DPRINT1("SERVICES: failed to create SCM database (Status %lx)\n", Status); + DPRINT1("SERVICES: failed to create SCM database (Error %lu)\n", dwError); ExitThread(0); }
_____
Modified: trunk/reactos/subsys/system/services/services.h --- trunk/reactos/subsys/system/services/services.h 2005-11-06 10:48:14 UTC (rev 19025) +++ trunk/reactos/subsys/system/services/services.h 2005-11-06 11:56:56 UTC (rev 19026) @@ -14,7 +14,7 @@
LIST_ENTRY ServiceListEntry; LPWSTR lpServiceName; LPWSTR lpDisplayName; - UNICODE_STRING ServiceGroup; + LPWSTR lpServiceGroup; BOOL bDeleted;
SERVICE_STATUS Status; @@ -47,14 +47,25 @@ REGSAM samDesired, PHKEY phKey);
+DWORD ScmCreateServiceKey(LPWSTR lpServiceName, + REGSAM samDesired, + PHKEY phKey); + DWORD ScmWriteDependencies(HKEY hServiceKey, LPWSTR lpDependencies, DWORD dwDependenciesLength);
+DWORD ScmMarkServiceForDelete(PSERVICE pService); +BOOL ScmIsDeleteFlagSet(HKEY hServiceKey);
+DWORD ScmReadString(HKEY hServiceKey, + LPWSTR lpValueName, + LPWSTR *lpValue); + + /* database.c */
-NTSTATUS ScmCreateServiceDataBase(VOID); +DWORD ScmCreateServiceDatabase(VOID); VOID ScmGetBootAndSystemDriverState(VOID); VOID ScmAutoStartServices(VOID);