[ros-diffs] [ekohl] 53872: [SERVICES] Assign a new Tag to new or changed services. Patch by Thomas Faber! See issue #6147 for more details.

ekohl at svn.reactos.org ekohl at svn.reactos.org
Tue Sep 27 12:42:42 UTC 2011


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/rpcserver.c?rev=53872&r1=53871&r2=53872&view=diff
==============================================================================
--- 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;
 }
 
 




More information about the Ros-diffs mailing list