Reactos
at master 259 lines 7.7 kB view raw
1/* 2 * PROJECT: ReactOS Service Control Manager 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/system/services/groupdb.c 5 * PURPOSE: Service group control interface 6 * COPYRIGHT: Copyright 2005 Eric Kohl 7 * 8 */ 9 10/* INCLUDES *****************************************************************/ 11 12#include "services.h" 13 14#define NDEBUG 15#include <debug.h> 16 17/* GLOBALS *******************************************************************/ 18 19LIST_ENTRY GroupListHead; 20LIST_ENTRY UnknownGroupListHead; 21 22 23/* FUNCTIONS *****************************************************************/ 24 25PSERVICE_GROUP 26ScmGetServiceGroupByName( 27 _In_ LPCWSTR lpGroupName) 28{ 29 PLIST_ENTRY GroupEntry; 30 PSERVICE_GROUP lpGroup; 31 32 DPRINT("ScmGetServiceGroupByName(%S)\n", lpGroupName); 33 34 GroupEntry = GroupListHead.Flink; 35 while (GroupEntry != &GroupListHead) 36 { 37 lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); 38 39 if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName)) 40 return lpGroup; 41 42 GroupEntry = GroupEntry->Flink; 43 } 44 45 GroupEntry = UnknownGroupListHead.Flink; 46 while (GroupEntry != &UnknownGroupListHead) 47 { 48 lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); 49 50 if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName)) 51 return lpGroup; 52 53 GroupEntry = GroupEntry->Flink; 54 } 55 56 return NULL; 57} 58 59 60DWORD 61ScmSetServiceGroup(PSERVICE lpService, 62 LPCWSTR lpGroupName) 63{ 64 PLIST_ENTRY GroupEntry; 65 PSERVICE_GROUP lpGroup; 66 67 DPRINT("ScmSetServiceGroup(%S)\n", lpGroupName); 68 69 if (lpService->lpGroup != NULL) 70 { 71 ASSERT(lpService->lpGroup->dwRefCount != 0); 72 ASSERT(lpService->lpGroup->dwRefCount == (DWORD)-1 || 73 lpService->lpGroup->dwRefCount < 10000); 74 if (lpService->lpGroup->dwRefCount != (DWORD)-1) 75 { 76 lpService->lpGroup->dwRefCount--; 77 if (lpService->lpGroup->dwRefCount == 0) 78 { 79 ASSERT(lpService->lpGroup->TagCount == 0); 80 ASSERT(lpService->lpGroup->TagArray == NULL); 81 RemoveEntryList(&lpService->lpGroup->GroupListEntry); 82 HeapFree(GetProcessHeap(), 0, lpService->lpGroup); 83 lpService->lpGroup = NULL; 84 } 85 } 86 } 87 88 if (lpGroupName == NULL) 89 return ERROR_SUCCESS; 90 91 GroupEntry = GroupListHead.Flink; 92 while (GroupEntry != &GroupListHead) 93 { 94 lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); 95 96 if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName)) 97 { 98 lpService->lpGroup = lpGroup; 99 return ERROR_SUCCESS; 100 } 101 102 GroupEntry = GroupEntry->Flink; 103 } 104 105 GroupEntry = UnknownGroupListHead.Flink; 106 while (GroupEntry != &UnknownGroupListHead) 107 { 108 lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); 109 110 if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName)) 111 { 112 lpGroup->dwRefCount++; 113 lpService->lpGroup = lpGroup; 114 return ERROR_SUCCESS; 115 } 116 117 GroupEntry = GroupEntry->Flink; 118 } 119 120 lpGroup = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(), 121 HEAP_ZERO_MEMORY, 122 sizeof(SERVICE_GROUP) + ((wcslen(lpGroupName) + 1)* sizeof(WCHAR))); 123 if (lpGroup == NULL) 124 return ERROR_NOT_ENOUGH_MEMORY; 125 126 wcscpy(lpGroup->szGroupName, lpGroupName); 127 lpGroup->lpGroupName = lpGroup->szGroupName; 128 lpGroup->dwRefCount = 1; 129 lpService->lpGroup = lpGroup; 130 131 InsertTailList(&UnknownGroupListHead, 132 &lpGroup->GroupListEntry); 133 134 return ERROR_SUCCESS; 135} 136 137 138static NTSTATUS WINAPI 139CreateGroupOrderListRoutine(PWSTR ValueName, 140 ULONG ValueType, 141 PVOID ValueData, 142 ULONG ValueLength, 143 PVOID Context, 144 PVOID EntryContext) 145{ 146 PSERVICE_GROUP Group; 147 148 DPRINT("CreateGroupOrderListRoutine(%S, %x, %p, %x, %p, %p)\n", 149 ValueName, ValueType, ValueData, ValueLength, Context, EntryContext); 150 151 if (ValueType == REG_BINARY && 152 ValueData != NULL && 153 ValueLength >= sizeof(DWORD) && 154 ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD)) 155 { 156 Group = (PSERVICE_GROUP)Context; 157 Group->TagCount = ((PULONG)ValueData)[0]; 158 if (Group->TagCount > 0) 159 { 160 if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD)) 161 { 162 Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(), 163 HEAP_ZERO_MEMORY, 164 Group->TagCount * sizeof(DWORD)); 165 if (Group->TagArray == NULL) 166 { 167 Group->TagCount = 0; 168 return STATUS_INSUFFICIENT_RESOURCES; 169 } 170 171 RtlCopyMemory(Group->TagArray, 172 (PULONG)ValueData + 1, 173 Group->TagCount * sizeof(DWORD)); 174 } 175 else 176 { 177 Group->TagCount = 0; 178 return STATUS_UNSUCCESSFUL; 179 } 180 } 181 } 182 183 return STATUS_SUCCESS; 184} 185 186 187static NTSTATUS WINAPI 188CreateGroupListRoutine(PWSTR ValueName, 189 ULONG ValueType, 190 PVOID ValueData, 191 ULONG ValueLength, 192 PVOID Context, 193 PVOID EntryContext) 194{ 195 PSERVICE_GROUP Group; 196 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 197 NTSTATUS Status; 198 199 if (ValueType == REG_SZ) 200 { 201 DPRINT("Data: '%S'\n", (PWCHAR)ValueData); 202 203 Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(), 204 HEAP_ZERO_MEMORY, 205 sizeof(SERVICE_GROUP) + ((wcslen((const wchar_t*) ValueData) + 1) * sizeof(WCHAR))); 206 if (Group == NULL) 207 { 208 return STATUS_INSUFFICIENT_RESOURCES; 209 } 210 211 wcscpy(Group->szGroupName, (const wchar_t*) ValueData); 212 Group->lpGroupName = Group->szGroupName; 213 Group->dwRefCount = (DWORD)-1; 214 215 RtlZeroMemory(&QueryTable, sizeof(QueryTable)); 216 QueryTable[0].Name = (PWSTR)ValueData; 217 QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine; 218 219 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, 220 L"GroupOrderList", 221 QueryTable, 222 (PVOID)Group, 223 NULL); 224 DPRINT("%x %lu %S\n", Status, Group->TagCount, (PWSTR)ValueData); 225 226 InsertTailList(&GroupListHead, 227 &Group->GroupListEntry); 228 } 229 230 return STATUS_SUCCESS; 231} 232 233 234DWORD 235ScmCreateGroupList(VOID) 236{ 237 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 238 NTSTATUS Status; 239 240 InitializeListHead(&GroupListHead); 241 InitializeListHead(&UnknownGroupListHead); 242 243 /* Build group order list */ 244 RtlZeroMemory(&QueryTable, 245 sizeof(QueryTable)); 246 247 QueryTable[0].Name = L"List"; 248 QueryTable[0].QueryRoutine = CreateGroupListRoutine; 249 250 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, 251 L"ServiceGroupOrder", 252 QueryTable, 253 NULL, 254 NULL); 255 256 return RtlNtStatusToDosError(Status); 257} 258 259/* EOF */