Author: ekohl
Date: Tue Sep 27 12:42:42 2011
New Revision: 53872
URL:
http://svn.reactos.org/svn/reactos?rev=53872&view=rev
Log:
[SERVICES]
Assign a new Tag to new or changed services.
Patch by Thomas Faber!
See issue #6147 for more details.
Modified:
trunk/reactos/base/system/services/rpcserver.c
Modified: trunk/reactos/base/system/services/rpcserver.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/rpcse…
==============================================================================
--- trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] Tue Sep 27 12:42:42 2011
@@ -77,6 +77,7 @@
SERVICE_STOP | \
SERVICE_START)
+#define TAG_ARRAY_SIZE 32
/* VARIABLES ***************************************************************/
@@ -263,10 +264,124 @@
DWORD
ScmAssignNewTag(PSERVICE lpService)
{
- /* FIXME */
- DPRINT("Assigning new tag to service %S\n", lpService->lpServiceName);
- lpService->dwTag = 0;
- return ERROR_SUCCESS;
+ HKEY hKey = NULL;
+ DWORD dwError;
+ DWORD dwGroupTagCount = 0;
+ PDWORD pdwGroupTags = NULL;
+ DWORD dwFreeTag = 0;
+ DWORD dwTagUsedBase = 1;
+ BOOLEAN TagUsed[TAG_ARRAY_SIZE];
+ DWORD dwTagOffset;
+ DWORD i;
+ DWORD cbDataSize;
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+
L"System\\CurrentControlSet\\Control\\GroupOrderList",
+ 0,
+ KEY_READ,
+ &hKey);
+
+ if (dwError != ERROR_SUCCESS)
+ goto findFreeTag;
+
+ /* query value length */
+ cbDataSize = 0;
+ dwError = RegQueryValueExW(hKey,
+ lpService->lpGroup->szGroupName,
+ NULL,
+ NULL,
+ NULL,
+ &cbDataSize);
+
+ if (dwError != ERROR_MORE_DATA)
+ goto findFreeTag;
+
+ pdwGroupTags = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
+ if (!pdwGroupTags)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
+ }
+
+ dwError = RegQueryValueExW(hKey,
+ lpService->lpGroup->szGroupName,
+ NULL,
+ NULL,
+ (LPBYTE)pdwGroupTags,
+ &cbDataSize);
+
+ if (dwError != ERROR_SUCCESS)
+ goto findFreeTag;
+
+ dwGroupTagCount = min(pdwGroupTags[0], cbDataSize / sizeof(pdwGroupTags[0]));
+
+findFreeTag:
+ do
+ {
+ /* mark all tags as unused */
+ for (i = 0; i < TAG_ARRAY_SIZE; i++)
+ TagUsed[i] = FALSE;
+
+ /* mark tags in GroupOrderList as used */
+ for (i = 1; i <= dwGroupTagCount; i++)
+ {
+ dwTagOffset = pdwGroupTags[i] - dwTagUsedBase;
+ if (dwTagOffset >= 0 && dwTagOffset < TAG_ARRAY_SIZE)
+ TagUsed[dwTagOffset] = TRUE;
+ }
+
+ /* mark tags in service list as used */
+ ServiceEntry = lpService->ServiceListEntry.Flink;
+ while (ServiceEntry != &lpService->ServiceListEntry)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
+ if (CurrentService->lpGroup == lpService->lpGroup)
+ {
+ dwTagOffset = CurrentService->dwTag - dwTagUsedBase;
+ if (dwTagOffset >= 0 && dwTagOffset < TAG_ARRAY_SIZE)
+ TagUsed[dwTagOffset] = TRUE;
+ }
+
+ ServiceEntry = ServiceEntry->Flink;
+ }
+
+ /* find unused tag, if any */
+ for (i = 0; i < TAG_ARRAY_SIZE; i++)
+ {
+ if (!TagUsed[i])
+ {
+ dwFreeTag = dwTagUsedBase + i;
+ break;
+ }
+ }
+
+ dwTagUsedBase += TAG_ARRAY_SIZE;
+ }
+ while (!dwFreeTag);
+
+cleanup:
+ if (pdwGroupTags)
+ HeapFree(GetProcessHeap(), 0, pdwGroupTags);
+
+ if (hKey)
+ RegCloseKey(hKey);
+
+ if (dwFreeTag)
+ {
+ lpService->dwTag = dwFreeTag;
+ DPRINT("Assigning new tag %lu to service %S in group %S\n",
+ lpService->dwTag, lpService->lpServiceName,
lpService->lpGroup->szGroupName);
+ dwError = ERROR_SUCCESS;
+ }
+ else
+ {
+ DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
+ lpService->lpServiceName, dwError);
+ }
+
+ return dwError;
}