[SMSS]
authorEric Kohl <eric.kohl@reactos.org>
Sat, 24 Sep 2011 15:12:52 +0000 (15:12 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sat, 24 Sep 2011 15:12:52 +0000 (15:12 +0000)
Fix wrong behavior of the "native applications startup at boot time" feature in SMSS.

Modifications:
- Added missing buffer allocation checks.
- Check for presence of default path.
- Minor clean-ups.
- Fix bad indentation/coding style.

Original patch by Hermès BÉLUSCA.
See issue #6180 for more details.

svn path=/trunk/; revision=53839

reactos/base/system/smss/initrun.c

index ff35e57..e656bd2 100644 (file)
@@ -26,69 +26,161 @@ SmpRunBootAppsQueryRoutine(PWSTR ValueName,
                          PVOID Context,
                          PVOID EntryContext)
 {
-  WCHAR Description [MAX_PATH];
-  WCHAR ImageName [MAX_PATH];
-  WCHAR ImagePath [MAX_PATH];
-  WCHAR CommandLine [MAX_PATH];
-  PWSTR p1, p2;
-  ULONG len;
-  NTSTATUS Status;
+    PCWSTR DefaultPath = L"\\SystemRoot\\system32\\";
+    PCWSTR DefaultExtension = L".exe";
+    PWSTR ImageName = NULL;
+    PWSTR ImagePath = NULL;
+    PWSTR CommandLine = NULL;
+    PWSTR p1 = (PWSTR)ValueData;
+    PWSTR p2 = (PWSTR)ValueData;
+    ULONG len = 0;
+    BOOLEAN HasAutocheckToken;
+    BOOLEAN HasNoExtension;
+    BOOLEAN HasDefaultPath;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
+    DPRINT("ValueData '%S'\n", (PWSTR)ValueData);
+
+    if (ValueType != REG_SZ)
+        return STATUS_SUCCESS;
+
+    /* Skip leading spaces */
+    while (*p1 == L' ')
+       p1++;
+
+    /* Get the next token */
+    p2 = wcschr(p1, L' ');
+    if (p2 == NULL)
+        p2 = p1 + wcslen(p1);
+    len = p2 - p1;
 
-  DPRINT("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
-  DPRINT("ValueData '%S'\n", (PWSTR)ValueData);
+    /* Check whether or not we have the 'autocheck' token */
+    HasAutocheckToken = ((len == 9) && (_wcsnicmp(p1, L"autocheck", 9) == 0));
 
-  if (ValueType != REG_SZ)
+    if (HasAutocheckToken)
     {
-      return(STATUS_SUCCESS);
+        /* Skip the current (autocheck) token */
+        p1 = p2;
+
+        /* Skip spaces */
+        while (*p1 == L' ')
+            p1++;
+
+        /* Get the next token */
+        p2 = wcschr(p1, L' ');
+        if (p2 == NULL)
+            p2 = p1 + wcslen(p1);
+        len = p2 - p1;
     }
 
-  /* Extract the description */
-  p1 = wcschr((PWSTR)ValueData, L' ');
-  len = p1 - (PWSTR)ValueData;
-  memcpy(Description,ValueData, len * sizeof(WCHAR));
-  Description[len] = 0;
+    /*
+     * Now, p1-->p2 is the image name and len is its length.
+     * If the image name is "" (empty string), then we stop
+     * here, we don't execute anything and return STATUS_SUCCESS.
+     */
+    if (len == 0)
+        return STATUS_SUCCESS;
+
+    /* Allocate the image name buffer */
+    ImageName = RtlAllocateHeap(SmpHeap, HEAP_ZERO_MEMORY, (len + 1) * sizeof(WCHAR));
+    if (ImageName == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto Done;
+    }
 
-  /* Extract the image name */
-  p1++;
-  p2 = wcschr(p1, L' ');
-  if (p2 != NULL)
-    len = p2 - p1;
-  else
+    /* Extract the image name */
+    memmove(ImageName, p1, len * sizeof(WCHAR));
+
+    /* Skip the current token */
+    p1 = p2;
+
+    /* Skip spaces */
+    while (*p1 == L' ')
+        p1++;
+
+    /* Get the length of the command line */
     len = wcslen(p1);
-  memcpy(ImageName, p1, len * sizeof(WCHAR));
-  ImageName[len] = 0;
 
-  /* Extract the command line */
-  if (p2 == NULL)
+    /* Allocate the command line buffer */
+    CommandLine = RtlAllocateHeap(SmpHeap, HEAP_ZERO_MEMORY, (len + 1) * sizeof(WCHAR));
+    if (CommandLine == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto Done;
+    }
+
+    /* Extract the command line. */
+    memmove(CommandLine, p1, len * sizeof(WCHAR));
+
+    /* Determine the image path length */
+    HasDefaultPath = (_wcsnicmp(ImageName, DefaultPath, wcslen(DefaultPath)) == 0);
+    HasNoExtension = (wcsrchr(ImageName, L'.') == NULL);
+
+    len = wcslen(ImageName);
+
+    if (!HasDefaultPath)
+        len += wcslen(DefaultPath);
+
+    if (HasNoExtension)
+        len += wcslen(DefaultExtension);
+
+    /* Allocate the image path buffer */
+    ImagePath = RtlAllocateHeap(SmpHeap, HEAP_ZERO_MEMORY, (len + 1) * sizeof(WCHAR));
+    if (ImagePath == NULL)
     {
-      CommandLine[0] = 0;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto Done;
     }
-  else
+
+    /* Build the image path */
+    if (HasDefaultPath)
     {
-      p2++;
-      wcscpy(CommandLine, p2);
+        wcscpy(ImagePath, ImageName);
+    }
+    else
+    {
+        wcscpy(ImagePath, DefaultPath);
+        wcscat(ImagePath, ImageName);
     }
 
-  DPRINT("Running %S...\n", Description);
-  DPRINT("ImageName: '%S'\n", ImageName);
-  DPRINT("CommandLine: '%S'\n", CommandLine);
+    if (HasNoExtension)
+        wcscat(ImagePath, DefaultExtension);
 
-  /* initialize executable path */
-  wcscpy(ImagePath, L"\\SystemRoot\\system32\\");
-  wcscat(ImagePath, ImageName);
-  wcscat(ImagePath, L".exe");
+    DPRINT("ImageName  : '%S'\n", ImageName);
+    DPRINT("ImagePath  : '%S'\n", ImagePath);
+    DPRINT("CommandLine: '%S'\n", CommandLine);
 
-  /* Create NT process */
-  Status = SmCreateUserProcess (ImagePath,
-                               CommandLine,
-                               SM_CREATE_FLAG_WAIT,
-                               NULL, NULL);
-  if (!NT_SUCCESS(Status))
-  {
-               DPRINT1("SM: %s: running '%S' failed (Status=0x%08lx)\n",
-                       __FUNCTION__, ImagePath, Status);
-  }
-  return(STATUS_SUCCESS);
+    /* Create NT process */
+    Status = SmCreateUserProcess(ImagePath,
+                                 CommandLine,
+                                 SM_CREATE_FLAG_WAIT,
+                                 NULL, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("SM: %s: running '%S' failed (Status=0x%08lx)\n",
+                __FUNCTION__, ImageName, Status);
+
+        if (HasAutocheckToken)
+            PrintString("%S program not found - skipping AUTOCHECK\n", ImageName);
+
+        /* No need to return an error */
+        Status = STATUS_SUCCESS;
+    }
+
+Done:
+    /* Free the buffers */
+    if (ImagePath != NULL)
+        RtlFreeHeap(SmpHeap, 0, ImagePath);
+
+    if (CommandLine != NULL)
+        RtlFreeHeap(SmpHeap, 0, CommandLine);
+
+    if (ImageName != NULL)
+        RtlFreeHeap(SmpHeap, 0, ImageName);
+
+    return Status;
 }