diff --git a/reactos/base/system/smss/initrun.c b/reactos/base/system/smss/initrun.c index ff35e576a8f..e656bd22fa6 100644 --- a/reactos/base/system/smss/initrun.c +++ b/reactos/base/system/smss/initrun.c @@ -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); + DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + DPRINT("ValueData '%S'\n", (PWSTR)ValueData); - if (ValueType != REG_SZ) - { - return(STATUS_SUCCESS); - } + if (ValueType != REG_SZ) + return STATUS_SUCCESS; - /* Extract the description */ - p1 = wcschr((PWSTR)ValueData, L' '); - len = p1 - (PWSTR)ValueData; - memcpy(Description,ValueData, len * sizeof(WCHAR)); - Description[len] = 0; + /* Skip leading spaces */ + while (*p1 == L' ') + p1++; - /* Extract the image name */ - p1++; - p2 = wcschr(p1, L' '); - if (p2 != NULL) + /* Get the next token */ + p2 = wcschr(p1, L' '); + if (p2 == NULL) + p2 = p1 + wcslen(p1); len = p2 - p1; - else + + /* Check whether or not we have the 'autocheck' token */ + HasAutocheckToken = ((len == 9) && (_wcsnicmp(p1, L"autocheck", 9) == 0)); + + if (HasAutocheckToken) + { + /* 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; + } + + /* + * 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 */ + 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) { - CommandLine[0] = 0; - } - else - { - p2++; - wcscpy(CommandLine, p2); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Done; } - DPRINT("Running %S...\n", Description); - DPRINT("ImageName: '%S'\n", ImageName); - DPRINT("CommandLine: '%S'\n", CommandLine); + /* Extract the command line. */ + memmove(CommandLine, p1, len * sizeof(WCHAR)); - /* initialize executable path */ - wcscpy(ImagePath, L"\\SystemRoot\\system32\\"); - wcscat(ImagePath, ImageName); - wcscat(ImagePath, L".exe"); + /* Determine the image path length */ + HasDefaultPath = (_wcsnicmp(ImageName, DefaultPath, wcslen(DefaultPath)) == 0); + HasNoExtension = (wcsrchr(ImageName, L'.') == NULL); - /* 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); + 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) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + /* Build the image path */ + if (HasDefaultPath) + { + wcscpy(ImagePath, ImageName); + } + else + { + wcscpy(ImagePath, DefaultPath); + wcscat(ImagePath, ImageName); + } + + if (HasNoExtension) + wcscat(ImagePath, DefaultExtension); + + 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__, 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; }