[ros-diffs] [ion] 55333: [SMSS2]: Implement command line and token parsing. Implement pagefile descriptor structure, format, flags, and parsing. They are now created as they should. Use SmpHeap instead of RtlG...

ion at svn.reactos.org ion at svn.reactos.org
Mon Jan 30 19:29:30 UTC 2012


Author: ion
Date: Mon Jan 30 19:29:30 2012
New Revision: 55333

URL: http://svn.reactos.org/svn/reactos?rev=55333&view=rev
Log:
[SMSS2]: Implement command line and token parsing. Implement pagefile descriptor structure, format, flags, and parsing. They are now created as they should. Use SmpHeap instead of RtlGetProcessHeap() to keep code cleaner. Use SmpSystemRoot instead of NtSystemRoot now that it's being defined. "Environment" in registry should be parsed twice to handle nested expansions.

Modified:
    trunk/reactos/base/system/smss2/pagefile.c
    trunk/reactos/base/system/smss2/sminit.c
    trunk/reactos/base/system/smss2/smss.c
    trunk/reactos/base/system/smss2/smss.h
    trunk/reactos/base/system/smss2/smutil.c

Modified: trunk/reactos/base/system/smss2/pagefile.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/pagefile.c?rev=55333&r1=55332&r2=55333&view=diff
==============================================================================
--- trunk/reactos/base/system/smss2/pagefile.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/pagefile.c [iso-8859-1] Mon Jan 30 19:29:30 2012
@@ -14,7 +14,30 @@
 
 /* GLOBALS ********************************************************************/
 
+#define STANDARD_DRIVE_LETTER_OFFSET 4
+
+#define SMP_PAGEFILE_CREATED            0x01
+#define SMP_PAGEFILE_DEFAULT            0x02
+#define SMP_PAGEFILE_SYSTEM_MANAGED     0x04
+#define SMP_PAGEFILE_WAS_TOO_BIG        0x08
+#define SMP_PAGEFILE_ON_ANY_DRIVE       0x10
+#define SMP_PAGEFILE_EMERGENCY          0x20
+#define SMP_PAGEFILE_DUMP_PROCESSED     0x40
+typedef struct _SMP_PAGEFILE_DESCRIPTOR
+{
+    LIST_ENTRY Entry;
+    UNICODE_STRING Name;
+    UNICODE_STRING Token;
+    LARGE_INTEGER MinSize;
+    LARGE_INTEGER MaxSize;
+    LARGE_INTEGER ActualMinSize;
+    LARGE_INTEGER ActualMaxSize;
+    ULONG Flags;
+} SMP_PAGEFILE_DESCRIPTOR, *PSMP_PAGEFILE_DESCRIPTOR;
+
 LIST_ENTRY SmpPagingFileDescriptorList, SmpVolumeDescriptorList;
+BOOLEAN SmpRegistrySpecifierPresent;
+ULONG SmpNumberOfPagingFiles;
 
 /* FUNCTIONS ******************************************************************/
 
@@ -31,8 +54,157 @@
 NTAPI
 SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
 {
-    DPRINT1("New pagefile data: %wZ\n", PageFileToken);
-    return STATUS_SUCCESS;
+    NTSTATUS Status;
+    ULONG MinSize = 0, MaxSize = 0;
+    BOOLEAN SystemManaged = FALSE, ZeroSize = TRUE;
+    PSMP_PAGEFILE_DESCRIPTOR Descriptor, ListDescriptor;
+    ULONG i;
+    WCHAR c;
+    PWCHAR p, ArgBuffer;
+    PLIST_ENTRY NextEntry;
+    UNICODE_STRING PageFileName, Arguments;
+
+    /* Make sure we don't have too many */
+    if (SmpNumberOfPagingFiles >= 16)
+    {
+        DPRINT1("SMSS:PFILE: Too many paging files specified - %d\n",
+                SmpNumberOfPagingFiles);
+        return STATUS_TOO_MANY_PAGING_FILES;
+    }
+
+    /* Parse the specified and get the name and arguments out of it */
+    DPRINT1("SMSS:PFILE: Paging file specifier `%wZ' \n", PageFileToken);
+    Status = SmpParseCommandLine(PageFileToken,
+                                 NULL,
+                                 &PageFileName,
+                                 NULL,
+                                 &Arguments);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        DPRINT1("SMSS:PFILE: SmpParseCommandLine(%wZ) failed with status %X \n",
+                PageFileToken, Status);
+        return Status;
+    }
+
+    /* Set the variable to let everyone know we have a pagefile token */
+    SmpRegistrySpecifierPresent = TRUE;
+
+    /* Parse the arguments, if any */
+    if (Arguments.Buffer)
+    {
+        /* Parse the pagefile size */
+        for (i = 0; i < Arguments.Length / sizeof(WCHAR); i++)
+        {
+            /* Check if it's zero */
+            c = Arguments.Buffer[i];
+            if ((c != L' ') && (c != L'\t') && (c != L'0'))
+            {
+                /* It isn't, break out */
+                ZeroSize = FALSE;
+                break;
+            }
+        }
+    }
+
+    /* Was a pagefile not specified, or was it specified with no size? */
+    if ((Arguments.Buffer) || (ZeroSize))
+    {
+        /* In this case, the system will manage its size */
+        SystemManaged = TRUE;
+    }
+    else
+    {
+        /* We do have a size, so convert the arguments into a number */
+        Status = RtlUnicodeStringToInteger(&Arguments, 0, &MinSize);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Fail */
+            RtlFreeUnicodeString(&PageFileName);
+            RtlFreeUnicodeString(&Arguments);
+            return Status;
+        }
+
+        /* Now advance to the next argument */
+        ArgBuffer = Arguments.Buffer;
+        p = ArgBuffer;
+        while (*p++)
+        {
+            /* Which should be a space... */
+            if (*p == L' ')
+            {
+                /* And use the rest of the arguments as a maximum size */
+                Arguments.Length -= ((PCHAR)p - (PCHAR)ArgBuffer);
+                Arguments.Buffer = ArgBuffer;
+                Status = RtlUnicodeStringToInteger(&Arguments, 0, &MaxSize);
+                if (!NT_SUCCESS(Status))
+                {
+                    /* Fail */
+                    RtlFreeUnicodeString(&PageFileName);
+                    RtlFreeUnicodeString(&Arguments);
+                    return Status;
+                }
+
+                /* We have both min and max, restore argument buffer */
+                Arguments.Buffer = ArgBuffer; // Actual Windows Bug in faillure case above.
+                break;
+            }
+        }
+    }
+
+    /* We are done parsing arguments */
+    RtlFreeUnicodeString(&Arguments);
+
+    /* Now we can allocate our descriptor */
+    Descriptor = RtlAllocateHeap(RtlGetProcessHeap(),
+                                 HEAP_ZERO_MEMORY,
+                                 sizeof(SMP_PAGEFILE_DESCRIPTOR));
+    if (!Descriptor)
+    {
+        /* Fail if we couldn't */
+        RtlFreeUnicodeString(&PageFileName);
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Capture all our data into the descriptor */
+    Descriptor->Token = *PageFileToken;
+    Descriptor->Name = PageFileName;
+    Descriptor->MinSize.QuadPart = MinSize * 0x100000;
+    Descriptor->MaxSize.QuadPart = MaxSize * 0x100000;
+    if (SystemManaged) Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED;
+    Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] =
+    RtlUpcaseUnicodeChar(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET]);
+    if (Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == '?')
+    {
+        Descriptor->Flags |= SMP_PAGEFILE_ON_ANY_DRIVE;
+    }
+
+    /* Now loop the existing descriptors */
+    NextEntry = SmpPagingFileDescriptorList.Flink;
+    do
+    {
+        /* Are there none, or have we looped back to the beginning? */
+        if (NextEntry == &SmpPagingFileDescriptorList)
+        {
+            /* This means no duplicates exist, so insert our descriptor! */
+            InsertTailList(&SmpPagingFileDescriptorList, &Descriptor->Entry);
+            SmpNumberOfPagingFiles++;
+            DPRINT1("SMSS:PFILE: Created descriptor for `%wZ' (`%wZ') \n",
+                    PageFileToken, &Descriptor->Name);
+            return STATUS_SUCCESS;
+        }
+
+        /* Keep going until we find a duplicate, unless we are in "any" mode */
+        ListDescriptor = CONTAINING_RECORD(NextEntry, SMP_PAGEFILE_DESCRIPTOR, Entry);
+        NextEntry = NextEntry->Flink;
+    } while (!(ListDescriptor->Flags & SMP_PAGEFILE_ON_ANY_DRIVE) ||
+             !(Descriptor->Flags & SMP_PAGEFILE_ON_ANY_DRIVE));
+
+    /* We found a duplicate, so skip this descriptor/pagefile and fail */
+    DPRINT1("SMSS:PFILE: Skipping duplicate specifier `%wZ' \n", PageFileToken);
+    RtlFreeUnicodeString(&PageFileName);
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Descriptor);
+    return STATUS_INVALID_PARAMETER;
 }
 
 NTSTATUS

Modified: trunk/reactos/base/system/smss2/sminit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/sminit.c?rev=55333&r1=55332&r2=55333&view=diff
==============================================================================
--- trunk/reactos/base/system/smss2/sminit.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/sminit.c [iso-8859-1] Mon Jan 30 19:29:30 2012
@@ -23,15 +23,14 @@
 } SMP_REGISTRY_VALUE, *PSMP_REGISTRY_VALUE;
 
 UNICODE_STRING SmpSubsystemName, PosixName, Os2Name;
-UNICODE_STRING SmpDebugKeyword, SmpASyncKeyword, SmpAutoChkKeyword;
 LIST_ENTRY SmpBootExecuteList, SmpSetupExecuteList, SmpPagingFileList;
 LIST_ENTRY SmpDosDevicesList, SmpFileRenameList, SmpKnownDllsList;
 LIST_ENTRY SmpExcludeKnownDllsList, SmpSubSystemList, SmpSubSystemsToLoad;
 LIST_ENTRY SmpSubSystemsToDefer, SmpExecuteList, NativeProcessList;
 
+PVOID SmpHeap;
 ULONG SmBaseTag;
 HANDLE SmpDebugPort, SmpDosDevicesObjectDirectory;
-PVOID SmpHeap;
 PWCHAR SmpDefaultEnvironment, SmpDefaultLibPathBuffer;
 UNICODE_STRING SmpKnownDllPath, SmpDefaultLibPath;
 ULONG SmpCalledConfigEnv;
@@ -720,6 +719,16 @@
         RTL_QUERY_REGISTRY_SUBKEY,
         L"KnownDlls",
         &SmpKnownDllsList,
+        REG_NONE,
+        NULL,
+        0
+    },
+
+    {
+        SmpConfigureEnvironment,
+        RTL_QUERY_REGISTRY_SUBKEY,
+        L"Environment",
+        NULL,
         REG_NONE,
         NULL,
         0

Modified: trunk/reactos/base/system/smss2/smss.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smss.c?rev=55333&r1=55332&r2=55333&view=diff
==============================================================================
--- trunk/reactos/base/system/smss2/smss.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smss.c [iso-8859-1] Mon Jan 30 19:29:30 2012
@@ -26,8 +26,7 @@
                                          sizeof(WCHAR);
 ULONG NtInitialUserProcessBufferType = REG_SZ;
 
-UNICODE_STRING NtSystemRoot;
-
+UNICODE_STRING SmpSystemRoot;
 ULONG AttachedSessionId = -1;
 BOOLEAN SmpDebug;
 
@@ -127,7 +126,7 @@
 
     /* Copy the DOS path */
     RtlCopyUnicodeString(&ProcessParams->CurrentDirectory.DosPath,
-                         &NtSystemRoot);
+                         &SmpSystemRoot);
 
     /* Make a buffer for the DLL Path */
     p = (PWSTR)((PCHAR)ProcessParams->CurrentDirectory.DosPath.Buffer +
@@ -195,7 +194,7 @@
     RtlAppendUnicodeStringToString(&Environment, &NullString);
 
     /* Create the system drive string */
-    SystemDriveString = NtSystemRoot;
+    SystemDriveString = SmpSystemRoot;
     SystemDriveString.Length = 2 * sizeof(WCHAR);
 
     /* Append it to the environment */
@@ -205,7 +204,7 @@
 
     /* Append the system root to the environment */
     RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
-    RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
+    RtlAppendUnicodeStringToString(&Environment, &SmpSystemRoot);
     RtlAppendUnicodeStringToString(&Environment, &NullString);
 
     /* Create SMSS process */
@@ -271,8 +270,8 @@
     /* No handles at first */
     Handles[0] = Handles[1] = NULL;
 
-    /* Setup system root */
-    RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
+    /* Initialize the system root */
+    RtlInitUnicodeString(&SmpSystemRoot, SharedUserData->NtSystemRoot);
 
     /* Allocate the initialization buffer */
     InitBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(INIT_BUFFER));

Modified: trunk/reactos/base/system/smss2/smss.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smss.h?rev=55333&r1=55332&r2=55333&view=diff
==============================================================================
--- trunk/reactos/base/system/smss2/smss.h [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smss.h [iso-8859-1] Mon Jan 30 19:29:30 2012
@@ -30,6 +30,11 @@
 
 /* DEFINES ********************************************************************/
 
+#define SMP_DEBUG_FLAG      0x01
+#define SMP_ASYNC_FLAG      0x02
+#define SMP_AUTOCHK_FLAG    0x04
+#define SMP_INVALID_PATH    0x10
+
 /* EXTERNALS ******************************************************************/
 
 extern RTL_CRITICAL_SECTION SmpKnownSubSysLock;
@@ -43,6 +48,12 @@
 extern HANDLE SmpSessionsObjectDirectory;
 extern HANDLE SmpWindowsSubSysProcessId;
 extern BOOLEAN RegPosixSingleInstance;
+extern UNICODE_STRING SmpDebugKeyword, SmpASyncKeyword, SmpAutoChkKeyword;
+extern PVOID SmpHeap;
+extern ULONG SmBaseTag;
+extern UNICODE_STRING SmpSystemRoot;
+extern PWCHAR SmpDefaultEnvironment;
+extern UNICODE_STRING SmpDefaultLibPath;
 
 /* FUNCTIONS ******************************************************************/
 
@@ -121,3 +132,12 @@
     VOID
 );
 
+NTSTATUS
+NTAPI
+SmpParseCommandLine(
+    IN PUNICODE_STRING CommandLine,
+    OUT PULONG Flags,
+    OUT PUNICODE_STRING FileName,
+    OUT PUNICODE_STRING Directory,
+    OUT PUNICODE_STRING Arguments
+);

Modified: trunk/reactos/base/system/smss2/smutil.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smutil.c?rev=55333&r1=55332&r2=55333&view=diff
==============================================================================
--- trunk/reactos/base/system/smss2/smutil.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smutil.c [iso-8859-1] Mon Jan 30 19:29:30 2012
@@ -23,6 +23,8 @@
     TOKEN_PRIVILEGES NewBuffer;
 } SMP_PRIVILEGE_STATE, *PSMP_PRIVILEGE_STATE;
 
+UNICODE_STRING SmpDebugKeyword, SmpASyncKeyword, SmpAutoChkKeyword;
+
 /* FUNCTIONS ******************************************************************/
 
 NTSTATUS
@@ -36,9 +38,9 @@
 
     /* Assume failure */
     *PrivilegeState = NULL;
-    
+
     /* Acquire the state structure to hold everything we need */
-    State = RtlAllocateHeap(RtlGetProcessHeap(),
+    State = RtlAllocateHeap(SmpHeap,
                             0,
                             sizeof(SMP_PRIVILEGE_STATE) +
                             sizeof(TOKEN_PRIVILEGES) +
@@ -52,7 +54,7 @@
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
-        RtlFreeHeap(RtlGetProcessHeap(), 0, State);
+        RtlFreeHeap(SmpHeap, 0, State);
         return Status;
     }
 
@@ -74,7 +76,7 @@
     if (Status == STATUS_BUFFER_TOO_SMALL)
     {
         /* Our static buffer is not big enough, allocate a bigger one */
-        State->OldPrivileges = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
+        State->OldPrivileges = RtlAllocateHeap(SmpHeap, 0, Size);
         if (!State->OldPrivileges)
         {
             /* Out of memory, fail */
@@ -105,12 +107,12 @@
     if (State->OldPrivileges != (PTOKEN_PRIVILEGES)&State->OldBuffer)
     {
         /* Free it */
-        RtlFreeHeap(RtlGetProcessHeap(), 0, State->OldPrivileges);
+        RtlFreeHeap(SmpHeap, 0, State->OldPrivileges);
     }
 
     /* Close the token handle and free the state structure */
     NtClose(State->TokenHandle);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, State);
+    RtlFreeHeap(SmpHeap, 0, State);
     return Status;
 }
 
@@ -119,7 +121,7 @@
 SmpReleasePrivilege(IN PVOID PrivState)
 {
     PSMP_PRIVILEGE_STATE State = (PSMP_PRIVILEGE_STATE)PrivState;
-    
+
     /* Adjust the privileges in the token */
     NtAdjustPrivilegesToken(State->TokenHandle,
                             FALSE,
@@ -132,10 +134,277 @@
     if (State->OldPrivileges != (PTOKEN_PRIVILEGES)&State->OldBuffer)
     {
         /* Free it */
-        RtlFreeHeap(RtlGetProcessHeap(), 0, State->OldPrivileges);
+        RtlFreeHeap(SmpHeap, 0, State->OldPrivileges);
     }
 
     /* Close the token handle and free the state structure */
     NtClose(State->TokenHandle);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, State);
+    RtlFreeHeap(SmpHeap, 0, State);
 }
+
+NTSTATUS
+NTAPI
+SmpParseToken(IN PUNICODE_STRING Input,
+              IN BOOLEAN SecondPass,
+              OUT PUNICODE_STRING Token)
+{
+    PWCHAR p, pp;
+    ULONG Length, TokenLength, InputLength;
+
+    /* Initialize to NULL to start with */
+    RtlInitUnicodeString(Token, NULL);
+
+    /* Save the input length */
+    InputLength = Input->Length;
+
+    /* Parse the buffer until the first character */
+    p = Input->Buffer;
+    Length = 0;
+    while (Length < InputLength)
+    {
+        if (*p > L' ' ) break;
+        ++p;
+        Length += sizeof(WCHAR);
+    }
+
+    /* Are we being called for argument pick-up? */
+    if (SecondPass)
+    {
+        /* Then assume everything else is an argument */
+        TokenLength = InputLength - Length * sizeof(WCHAR);
+        pp = (PWSTR)((ULONG_PTR)p + TokenLength);
+    }
+    else
+    {
+        /* No -- so loop until the next space */
+        pp = p;
+        while (Length < InputLength)
+        {
+            if (*pp <= L' ' ) break;
+            ++pp;
+            Length += sizeof(WCHAR);
+        }
+
+        /* Now compute how long this token is, and loop until the next char */
+        TokenLength = (ULONG_PTR)pp - (ULONG_PTR)p;
+        while (Length < InputLength)
+        {
+            if (*pp > L' ' ) break;
+            ++pp;
+            Length += sizeof(WCHAR);
+        }
+    }
+
+    /* Did we find a token? */
+    if (TokenLength)
+    {
+        /* Allocate a buffer for it */
+        Token->Buffer = RtlAllocateHeap(SmpHeap,
+                                        SmBaseTag,
+                                        TokenLength + sizeof(UNICODE_NULL));
+        if (!Token->Buffer) return STATUS_NO_MEMORY;
+
+        /* Fill in the unicode string to hold it */
+        Token->MaximumLength = TokenLength + sizeof(UNICODE_NULL);
+        Token->Length = TokenLength;
+        RtlCopyMemory(Token->Buffer, p, TokenLength);
+        Token->Buffer[TokenLength / sizeof(WCHAR)] = UNICODE_NULL;
+    }
+
+    /* Modify the input string with the position of where the next token begins */
+    Input->Length -= (ULONG_PTR)pp - (ULONG_PTR)Input->Buffer;
+    Input->Buffer = pp;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+SmpParseCommandLine(IN PUNICODE_STRING CommandLine,
+                    OUT PULONG Flags,
+                    OUT PUNICODE_STRING FileName,
+                    OUT PUNICODE_STRING Directory,
+                    OUT PUNICODE_STRING Arguments)
+{
+    ULONG Length;
+    UNICODE_STRING EnvString, PathString, CmdLineCopy, Token;
+    WCHAR PathBuffer[MAX_PATH];
+    PWCHAR FilePart;
+    NTSTATUS Status;
+    UNICODE_STRING FullPathString;
+
+    /* Initialize output arguments to NULL */
+    RtlInitUnicodeString(FileName, NULL);
+    RtlInitUnicodeString(Arguments, NULL);
+    if (Directory) RtlInitUnicodeString(Directory, NULL);
+
+    /* Check if we haven't yet built a full default path or system root yet */
+    if (!SmpSystemRoot.Length)
+    {
+        /* Initialize it based on shared user data string */
+        RtlInitUnicodeString(&SmpSystemRoot, SharedUserData->NtSystemRoot);
+
+        /* Allocate an empty string for the path */
+        Length = SmpDefaultLibPath.MaximumLength + SmpSystemRoot.MaximumLength +
+                 sizeof(L"\\system32;");
+        RtlInitEmptyUnicodeString(&FullPathString,
+                                  RtlAllocateHeap(SmpHeap, SmBaseTag, Length),
+                                  Length);
+        if (FullPathString.Buffer)
+        {
+            /* Append the root, system32;, and then the current library path */
+            RtlAppendUnicodeStringToString(&FullPathString, &SmpSystemRoot);
+            RtlAppendUnicodeToString(&FullPathString, L"\\system32;");
+            RtlAppendUnicodeStringToString(&FullPathString, &SmpDefaultLibPath);
+            RtlFreeHeap(SmpHeap, 0, SmpDefaultLibPath.Buffer);
+            SmpDefaultLibPath = FullPathString;
+        }
+    }
+
+    /* Consume the command line */
+    CmdLineCopy = *CommandLine;
+    while (TRUE)
+    {
+        /* Parse the first token and check for modifiers/specifiers */
+        Status = SmpParseToken(&CmdLineCopy, FALSE, &Token);
+        if (!(NT_SUCCESS(Status)) || !(Token.Buffer)) return STATUS_UNSUCCESSFUL;
+        if (!Flags) break;
+
+        /* Debug requested? */
+        if (RtlEqualUnicodeString(&Token, &SmpDebugKeyword, TRUE))
+        {
+            /* Convert into a flag */
+            *Flags |= SMP_DEBUG_FLAG;
+        }
+        else if (RtlEqualUnicodeString(&Token, &SmpASyncKeyword, TRUE))
+        {
+            /* Asynch requested, convert into a flag */
+            *Flags |= SMP_ASYNC_FLAG;
+        }
+        else if (RtlEqualUnicodeString(&Token, &SmpAutoChkKeyword, TRUE))
+        {
+            /* Autochk requested, convert into a flag */
+            *Flags |= SMP_AUTOCHK_FLAG;
+        }
+        else
+        {
+            /* No specifier found, keep going */
+            break;
+        }
+
+        /* Get rid of this token and get the next */
+        RtlFreeHeap(SmpHeap, 0, Token.Buffer);
+    }
+
+    /* Initialize a string to hold the current path */
+    RtlInitUnicodeString(&EnvString, L"Path");
+    Length = PAGE_SIZE;
+    RtlInitEmptyUnicodeString(&PathString,
+                              RtlAllocateHeap(SmpHeap, SmBaseTag, Length),
+                              Length);
+    if (!PathString.Buffer)
+    {
+        /* Fail if we have no memory for this */
+        RtlFreeHeap(SmpHeap, 0, Token.Buffer);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Query the path from the environment */
+    Status = RtlQueryEnvironmentVariable_U(SmpDefaultEnvironment,
+                                           &EnvString,
+                                           &PathString);
+    if (Status == STATUS_BUFFER_TOO_SMALL)
+    {
+        /* Our buffer was too small, free it */
+        RtlFreeHeap(SmpHeap, 0, PathString.Buffer);
+
+        /* And allocate one big enough */
+        Length = PathString.Length + sizeof(UNICODE_NULL);
+        RtlInitEmptyUnicodeString(&PathString,
+                                  RtlAllocateHeap(SmpHeap, SmBaseTag, Length),
+                                  Length);
+        if (!PathString.Buffer)
+        {
+            /* Fail if we have no memory for this */
+            RtlFreeHeap(SmpHeap, 0, Token.Buffer);
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        /* Now try again, this should work */
+        Status = RtlQueryEnvironmentVariable_U(SmpDefaultEnvironment,
+                                               &EnvString,
+                                               &PathString);
+    }
+    if (!NT_SUCCESS(Status))
+    {
+        /* Another failure means that the kernel hasn't passed the path correctly */
+        DPRINT1("SMSS: %wZ environment variable not defined.\n", &EnvString);
+        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+    else
+    {
+        /* Check if the caller expects any flags out of here */
+        if (Flags)
+        {
+            /* We can return the image not found flag -- so does the image exist */
+            if (!(RtlDosSearchPath_U(PathString.Buffer,
+                                     Token.Buffer,
+                                     L".exe",
+                                     sizeof(PathBuffer),
+                                     PathBuffer,
+                                     &FilePart)) &&
+                !(RtlDosSearchPath_U(SmpDefaultLibPath.Buffer,
+                                     Token.Buffer,
+                                     L".exe",
+                                     sizeof(PathBuffer),
+                                     PathBuffer,
+                                     &FilePart)))
+            {
+                /* It doesn't, let the caller know about it and exit */
+                *Flags |= SMP_INVALID_PATH;
+                *FileName = Token;
+                RtlFreeHeap(SmpHeap, 0, PathString.Buffer);
+                return STATUS_SUCCESS;
+            }
+        }
+        else
+        {
+            /* Caller doesn't want flags, probably wants the image itself */
+            wcscpy(PathBuffer, Token.Buffer);
+        }
+    }
+
+    /* Free tokens and such, all that's left is to convert the image name */
+    RtlFreeHeap(SmpHeap, 0, Token.Buffer);
+    RtlFreeHeap(SmpHeap, 0, PathString.Buffer);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Convert it and bail out if this failed */
+    if (!RtlDosPathNameToNtPathName_U(PathBuffer, FileName, NULL, NULL))
+    {
+        DPRINT1("SMSS: Unable to translate %ws into an NT File Name\n",
+                &PathBuffer);
+        Status = STATUS_OBJECT_PATH_INVALID;
+    }
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Finally, check if the caller also wanted the directory */
+    if (Directory)
+    {
+        /* Is the file a relative name with no directory? */
+        if (FilePart <= PathBuffer)
+        {
+            /* Clear it */
+            RtlInitUnicodeString(Directory, NULL);
+        }
+        else
+        {
+            /* There is a directory, and a filename -- separate those two */
+            FilePart -= sizeof(UNICODE_NULL);
+            *FilePart = UNICODE_NULL;
+            RtlCreateUnicodeString(Directory, PathBuffer);
+        }
+    }
+
+    /* We are done -- move on to the second pass to get the arguments */
+    return SmpParseToken(&CmdLineCopy, TRUE, Arguments);
+}




More information about the Ros-diffs mailing list