Exemplo n.º 1
0
NTSTATUS
RtlCreateProcessParameters(
    OUT PRTL_USER_PROCESS_PARAMETERS *pProcessParameters,
    IN PUNICODE_STRING ImagePathName,
    IN PUNICODE_STRING DllPath OPTIONAL,
    IN PUNICODE_STRING CurrentDirectory OPTIONAL,
    IN PUNICODE_STRING CommandLine OPTIONAL,
    IN PVOID Environment OPTIONAL,
    IN PUNICODE_STRING WindowTitle OPTIONAL,
    IN PUNICODE_STRING DesktopInfo OPTIONAL,
    IN PUNICODE_STRING ShellInfo OPTIONAL,
    IN PUNICODE_STRING RuntimeData OPTIONAL
    )

/*++

Routine Description:

    This function formats NT style RTL_USER_PROCESS_PARAMETERS
    record.  The record is self-contained in a single block of memory
    allocated by this function.  The allocation method is opaque and
    thus the record must be freed by calling the
    RtlDestroyProcessParameters function.

    The process parameters record is created in a de-normalized form,
    thus making it suitable for passing to the RtlCreateUserProcess
    function.  It is expected that the caller will fill in additional
    fields in the process parameters record after this function returns,
    but prior to calling RtlCreateUserProcess.

Arguments:

    pProcessParameters - Pointer to a variable that will receive the address
        of the process parameter structure created by this routine.  The
        memory for the structure is allocated in an opaque manner and must
        be freed by calling RtlDestroyProcessParameters.

    ImagePathName - Required parameter that is the fully qualified NT
        path name of the image file that will be used to create the process
        that will received these parameters.

    DllPath - An optional parameter that is an NT String variable pointing
        to the search path the NT Loader is to use in the target process
        when searching for Dll modules.  If not specified, then the Dll
        search path is filled in from the current process's Dll search
        path.

    CurrentDirectory - An optional parameter that is an NT String variable
        pointing to the default directory string for the target process.
        If not specified, then the current directory string is filled in
        from the current process's current directory string.

    CommandLine - An optional parameter that is an NT String variable that
        will be passed to the target process as its command line.  If not
        specified, then the command line passed to the target process will
        be a null string.

    Environment - An optional parameter that is an opaque pointer to an
        environment variable block of the type created by
        RtlCreateEnvironment routine.  If not specified, then the target
        process will receive a copy of the calling process's environment
        variable block.

    WindowTitle - An optional parameter that is an NT String variable that
        points to the title string the target process is to use for its
        main window.  If not specified, then a null string will be passed
        to the target process as its default window title.

    DesktopInfo - An optional parameter that is an NT String variable that
        contains uninterpreted data that is passed as is to the target
        process.  If not specified, the target process will receive a
        pointer to an empty string.

    ShellInfo - An optional parameter that is an NT String variable that
        contains uninterpreted data that is passed as is to the target
        process.  If not specified, the target process will receive a
        pointer to an empty string.

    RuntimeData - An optional parameter that is an NT String variable that
        contains uninterpreted data that is passed as is to the target
        process.  If not specified, the target process will receive a
        pointer to an empty string.

Return Value:

    STATUS_SUCCESS - The process parameters is De-Normalized and
        contains entries for each of the specified argument and variable
        strings.

    STATUS_BUFFER_TOO_SMALL - The specified process parameters buffer is
        too small to contain the argument and environment strings. The value
        of ProcessParameters->Length is modified to contain the buffer
        size needed to contain the argument and variable strings.

--*/

{
    PRTL_USER_PROCESS_PARAMETERS p;
    NTSTATUS Status;
    ULONG ByteCount;
    PWSTR pDst;
    PPEB Peb;
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
    HANDLE CurDirHandle;
    BOOLEAN PebLockAcquired = FALSE;

    //
    // Acquire the Peb Lock for the duration while we copy information out
    // of it.
    //

    Peb = NtCurrentPeb();
    ProcessParameters = Peb->ProcessParameters;

    Status = STATUS_SUCCESS;
    p = NULL;
    CurDirHandle = NULL;
    try {
        //
        //  Validate input parameters
        //

#define VALIDATE_STRING_PARAMETER(_x) \
    do { \
        ASSERT(ARGUMENT_PRESENT((_x))); \
        if (!ARGUMENT_PRESENT((_x))) { \
            Status = STATUS_INVALID_PARAMETER; \
            leave; \
        } \
        if (ARGUMENT_PRESENT((_x))) { \
            ASSERT((_x)->MaximumLength >= (_x)->Length); \
            ASSERT(((_x)->Length == 0) || ((_x)->Buffer != NULL)); \
            if (((_x)->MaximumLength < (_x)->Length) || \
                (((_x)->Length != 0) && ((_x)->Buffer == NULL))) { \
                Status = STATUS_INVALID_PARAMETER; \
                leave; \
            } \
        } \
    } while (0)

#define VALIDATE_OPTIONAL_STRING_PARAMETER(_x) \
    do { \
        if (ARGUMENT_PRESENT((_x))) { \
            ASSERT((_x)->MaximumLength >= (_x)->Length); \
            ASSERT(((_x)->Length == 0) || ((_x)->Buffer != NULL)); \
            if (((_x)->MaximumLength < (_x)->Length) || \
                (((_x)->Length != 0) && ((_x)->Buffer == NULL))) { \
                Status = STATUS_INVALID_PARAMETER; \
                leave; \
            } \
        } \
    } while (0)

        VALIDATE_STRING_PARAMETER (ImagePathName);
        VALIDATE_OPTIONAL_STRING_PARAMETER (DllPath);
        VALIDATE_OPTIONAL_STRING_PARAMETER (CurrentDirectory);
        VALIDATE_OPTIONAL_STRING_PARAMETER (CommandLine);
        VALIDATE_OPTIONAL_STRING_PARAMETER (WindowTitle);
        VALIDATE_OPTIONAL_STRING_PARAMETER (DesktopInfo);
        VALIDATE_OPTIONAL_STRING_PARAMETER (ShellInfo);
        VALIDATE_OPTIONAL_STRING_PARAMETER (RuntimeData);

#undef VALIDATE_STRING_PARAMETER
#undef VALIDATE_OPTIONAL_STRING_PARAMETER

        if (!ARGUMENT_PRESENT (CommandLine)) {
            CommandLine = ImagePathName;
        }

        if (!ARGUMENT_PRESENT (WindowTitle)) {
            WindowTitle = (PUNICODE_STRING)&NullString;
        }

        if (!ARGUMENT_PRESENT (DesktopInfo)) {
            DesktopInfo = (PUNICODE_STRING)&NullString;
        }

        if (!ARGUMENT_PRESENT (ShellInfo)) {
            ShellInfo = (PUNICODE_STRING)&NullString;
        }

        if (!ARGUMENT_PRESENT (RuntimeData)) {
            RuntimeData = (PUNICODE_STRING)&NullString;
        }

        //
        // Determine size need to contain the process parameter record
        // structure and all of the strings it will point to.  Each string
        // will be aligned on a ULONG byte boundary.
        // We do the ones we can outside of the peb lock.
        //

        ByteCount = sizeof (*ProcessParameters);
        ByteCount += ROUND_UP (DOS_MAX_PATH_LENGTH*2,        sizeof( ULONG ) );
        ByteCount += ROUND_UP (ImagePathName->Length + sizeof(UNICODE_NULL),    sizeof( ULONG ) );
        ByteCount += ROUND_UP (CommandLine->Length + sizeof(UNICODE_NULL),      sizeof( ULONG ) );
        ByteCount += ROUND_UP (WindowTitle->MaximumLength,   sizeof( ULONG ) );
        ByteCount += ROUND_UP (DesktopInfo->MaximumLength,   sizeof( ULONG ) );
        ByteCount += ROUND_UP (ShellInfo->MaximumLength,     sizeof( ULONG ) );
        ByteCount += ROUND_UP (RuntimeData->MaximumLength,   sizeof( ULONG ) );

        PebLockAcquired = TRUE;
        RtlAcquirePebLock ();

        //
        // For optional pointer parameters, default them to point to their
        // corresponding field in the current process's process parameter
        // structure or to a null string.
        //

        if (!ARGUMENT_PRESENT (DllPath)) {
            DllPath = &ProcessParameters->DllPath;
        }

        if (!ARGUMENT_PRESENT (CurrentDirectory)) {

            if (ProcessParameters->CurrentDirectory.Handle) {
                CurDirHandle = (HANDLE)((ULONG_PTR)ProcessParameters->CurrentDirectory.Handle & ~OBJ_HANDLE_TAGBITS);
                CurDirHandle = (HANDLE)((ULONG_PTR)CurDirHandle | RTL_USER_PROC_CURDIR_INHERIT);
            }
            CurrentDirectory = &ProcessParameters->CurrentDirectory.DosPath;
        } else {
            ASSERT(CurrentDirectory->MaximumLength >= CurrentDirectory->Length);
            ASSERT((CurrentDirectory->Length == 0) || (CurrentDirectory->Buffer != NULL));

            if (ProcessParameters->CurrentDirectory.Handle) {
                CurDirHandle = (HANDLE)((ULONG_PTR)ProcessParameters->CurrentDirectory.Handle & ~OBJ_HANDLE_TAGBITS);
                CurDirHandle = (HANDLE)((ULONG_PTR)CurDirHandle | RTL_USER_PROC_CURDIR_CLOSE);
            }
        }


        if (!ARGUMENT_PRESENT (Environment)) {
            Environment = ProcessParameters->Environment;
        }

        ByteCount += ROUND_UP (DllPath->MaximumLength,       sizeof( ULONG ) );

        //
        // Allocate memory for the process parameter record.
        //
        p = RtlAllocateHeap (RtlProcessHeap (), 0, ByteCount);

        if (p == NULL) {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }

        RtlZeroMemory (p, sizeof (*p));

        p->MaximumLength = ByteCount;
        p->Length = ByteCount;
        p->Flags = RTL_USER_PROC_PARAMS_NORMALIZED;
        p->DebugFlags = 0;
        p->Environment = Environment;
        p->CurrentDirectory.Handle = CurDirHandle;

        //
        // Inherits ^C inhibit information
        //

        p->ConsoleFlags = ProcessParameters->ConsoleFlags;

        pDst = (PWSTR)(p + 1);
        RtlpCopyProcString (&pDst,
                            &p->CurrentDirectory.DosPath,
                            CurrentDirectory,
                            DOS_MAX_PATH_LENGTH*2);

        RtlpCopyProcString (&pDst, &p->DllPath, DllPath, 0);
        RtlpCopyProcString (&pDst, &p->ImagePathName, ImagePathName, ImagePathName->Length + sizeof (UNICODE_NULL));
        if (CommandLine->Length == CommandLine->MaximumLength) {
            RtlpCopyProcString (&pDst, &p->CommandLine, CommandLine, 0);
        } else {
            RtlpCopyProcString (&pDst, &p->CommandLine, CommandLine, CommandLine->Length + sizeof (UNICODE_NULL));
        }

        RtlpCopyProcString (&pDst, &p->WindowTitle, WindowTitle, 0);
        RtlpCopyProcString (&pDst, &p->DesktopInfo, DesktopInfo, 0);
        RtlpCopyProcString (&pDst, &p->ShellInfo,   ShellInfo, 0);
        if (RuntimeData->Length != 0) {
            RtlpCopyProcString (&pDst, &p->RuntimeData, RuntimeData, 0);
        }
        *pProcessParameters = RtlDeNormalizeProcessParams (p);
        p = NULL;
    } finally {
        if (PebLockAcquired) {
            RtlReleasePebLock();
        }

        if (AbnormalTermination ()) {
            Status = STATUS_ACCESS_VIOLATION;
        }

        if (p != NULL) {
            RtlDestroyProcessParameters (p);
        }

    }

    return Status;
}
Exemplo n.º 2
0
/******************************************************************************
 *  RtlCreateProcessParameters  [NTDLL.@]
 */
NTSTATUS WINAPI RtlCreateProcessParameters( RTL_USER_PROCESS_PARAMETERS **result,
                                            const UNICODE_STRING *ImagePathName,
                                            const UNICODE_STRING *DllPath,
                                            const UNICODE_STRING *CurrentDirectoryName,
                                            const UNICODE_STRING *CommandLine,
                                            PWSTR Environment,
                                            const UNICODE_STRING *WindowTitle,
                                            const UNICODE_STRING *Desktop,
                                            const UNICODE_STRING *ShellInfo,
                                            const UNICODE_STRING *RuntimeInfo )
{
    static WCHAR empty[] = {0};
    static const UNICODE_STRING empty_str = { 0, sizeof(empty), empty };
    static const UNICODE_STRING null_str = { 0, 0, NULL };

    const RTL_USER_PROCESS_PARAMETERS *cur_params;
    SIZE_T size, total_size;
    void *ptr;
    NTSTATUS status;

    RtlAcquirePebLock();
    cur_params = NtCurrentTeb()->Peb->ProcessParameters;
    if (!DllPath) DllPath = &cur_params->DllPath;
    if (!CurrentDirectoryName)
    {
        if (NtCurrentTeb()->Tib.SubSystemTib)  /* FIXME: hack */
            CurrentDirectoryName = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir.DosPath;
        else
            CurrentDirectoryName = &cur_params->CurrentDirectory.DosPath;
    }
    if (!CommandLine) CommandLine = ImagePathName;
    if (!Environment) Environment = cur_params->Environment;
    if (!WindowTitle) WindowTitle = &empty_str;
    if (!Desktop) Desktop = &empty_str;
    if (!ShellInfo) ShellInfo = &empty_str;
    if (!RuntimeInfo) RuntimeInfo = &null_str;

    size = (sizeof(RTL_USER_PROCESS_PARAMETERS)
            + ImagePathName->MaximumLength
            + DllPath->MaximumLength
            + CurrentDirectoryName->MaximumLength
            + CommandLine->MaximumLength
            + WindowTitle->MaximumLength
            + Desktop->MaximumLength
            + ShellInfo->MaximumLength
            + RuntimeInfo->MaximumLength);

    total_size = size;
    ptr = NULL;
    if ((status = NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &total_size,
                                           MEM_COMMIT, PAGE_READWRITE )) == STATUS_SUCCESS)
    {
        RTL_USER_PROCESS_PARAMETERS *params = ptr;
        params->AllocationSize = total_size;
        params->Size           = size;
        params->Flags          = PROCESS_PARAMS_FLAG_NORMALIZED;
        params->ConsoleFlags   = cur_params->ConsoleFlags;
        params->Environment    = Environment;
        /* all other fields are zero */

        ptr = params + 1;
        append_unicode_string( &ptr, CurrentDirectoryName, &params->CurrentDirectory.DosPath );
        append_unicode_string( &ptr, DllPath, &params->DllPath );
        append_unicode_string( &ptr, ImagePathName, &params->ImagePathName );
        append_unicode_string( &ptr, CommandLine, &params->CommandLine );
        append_unicode_string( &ptr, WindowTitle, &params->WindowTitle );
        append_unicode_string( &ptr, Desktop, &params->Desktop );
        append_unicode_string( &ptr, ShellInfo, &params->ShellInfo );
        append_unicode_string( &ptr, RuntimeInfo, &params->RuntimeInfo );
        *result = RtlDeNormalizeProcessParams( params );
    }
    RtlReleasePebLock();
    return status;
}
Exemplo n.º 3
0
/*
 * @implemented
 */
NTSTATUS NTAPI
RtlCreateProcessParameters(PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
			   PUNICODE_STRING ImagePathName,
			   PUNICODE_STRING DllPath,
			   PUNICODE_STRING CurrentDirectory,
			   PUNICODE_STRING CommandLine,
			   PWSTR Environment,
			   PUNICODE_STRING WindowTitle,
			   PUNICODE_STRING DesktopInfo,
			   PUNICODE_STRING ShellInfo,
			   PUNICODE_STRING RuntimeData)
{
   PRTL_USER_PROCESS_PARAMETERS Param = NULL;
   ULONG Length = 0;
   PWCHAR Dest;
   UNICODE_STRING EmptyString;
   HANDLE CurrentDirectoryHandle;
   HANDLE ConsoleHandle;
   ULONG ConsoleFlags;

   DPRINT ("RtlCreateProcessParameters\n");

   RtlAcquirePebLock();

   EmptyString.Length = 0;
   EmptyString.MaximumLength = sizeof(WCHAR);
   EmptyString.Buffer = L"";

   if (RtlpGetMode() == UserMode)
     {
	if (DllPath == NULL)
	  DllPath = &NtCurrentPeb()->ProcessParameters->DllPath;
	if (Environment == NULL)
	  Environment  = NtCurrentPeb()->ProcessParameters->Environment;
	if (CurrentDirectory == NULL)
	  CurrentDirectory = &NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath;
	CurrentDirectoryHandle = NtCurrentPeb()->ProcessParameters->CurrentDirectory.Handle;
	ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
	ConsoleFlags = NtCurrentPeb()->ProcessParameters->ConsoleFlags;
     }
   else
     {
	if (DllPath == NULL)
	  DllPath = &EmptyString;
	if (CurrentDirectory == NULL)
	  CurrentDirectory = &EmptyString;
	CurrentDirectoryHandle = NULL;
	ConsoleHandle = NULL;
	ConsoleFlags = 0;
     }

   if (CommandLine == NULL)
     CommandLine = &EmptyString;
   if (WindowTitle == NULL)
     WindowTitle = &EmptyString;
   if (DesktopInfo == NULL)
     DesktopInfo = &EmptyString;
   if (ShellInfo == NULL)
     ShellInfo = &EmptyString;
   if (RuntimeData == NULL)
     RuntimeData = &EmptyString;

   /* size of process parameter block */
   Length = sizeof(RTL_USER_PROCESS_PARAMETERS);

   /* size of current directory buffer */
   Length += (MAX_PATH * sizeof(WCHAR));

   /* add string lengths */
   Length += ALIGN(DllPath->MaximumLength, sizeof(ULONG));
   Length += ALIGN(ImagePathName->Length + sizeof(WCHAR), sizeof(ULONG));
   Length += ALIGN(CommandLine->Length + sizeof(WCHAR), sizeof(ULONG));
   Length += ALIGN(WindowTitle->MaximumLength, sizeof(ULONG));
   Length += ALIGN(DesktopInfo->MaximumLength, sizeof(ULONG));
   Length += ALIGN(ShellInfo->MaximumLength, sizeof(ULONG));
   Length += ALIGN(RuntimeData->MaximumLength, sizeof(ULONG));

   /* Calculate the required block size */
   Param = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
   if (!Param)
     {
	RtlReleasePebLock();
	return STATUS_INSUFFICIENT_RESOURCES;
     }

   DPRINT ("Process parameters allocated\n");

   Param->MaximumLength = Length;
   Param->Length = Length;
   Param->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED;
   Param->Environment = Environment;
   Param->CurrentDirectory.Handle = CurrentDirectoryHandle;
   Param->ConsoleHandle = ConsoleHandle;
   Param->ConsoleFlags = ConsoleFlags;

   Dest = (PWCHAR)(((PBYTE)Param) + sizeof(RTL_USER_PROCESS_PARAMETERS));

   /* copy current directory */
   RtlpCopyParameterString(&Dest,
			   &Param->CurrentDirectory.DosPath,
			   CurrentDirectory,
			   MAX_PATH * sizeof(WCHAR));

   /* make sure the current directory has a trailing backslash */
   if (Param->CurrentDirectory.DosPath.Length > 0)
     {
	ULONG Length;

	Length = Param->CurrentDirectory.DosPath.Length / sizeof(WCHAR);
	if (Param->CurrentDirectory.DosPath.Buffer[Length-1] != L'\\')
	  {
	     Param->CurrentDirectory.DosPath.Buffer[Length] = L'\\';
	     Param->CurrentDirectory.DosPath.Buffer[Length + 1] = 0;
	     Param->CurrentDirectory.DosPath.Length += sizeof(WCHAR);
	  }
     }

   /* copy dll path */
   RtlpCopyParameterString(&Dest,
			   &Param->DllPath,
			   DllPath,
			   0);

   /* copy image path name */
   RtlpCopyParameterString(&Dest,
			   &Param->ImagePathName,
			   ImagePathName,
			   ImagePathName->Length + sizeof(WCHAR));

   /* copy command line */
   RtlpCopyParameterString(&Dest,
			   &Param->CommandLine,
			   CommandLine,
			   CommandLine->Length + sizeof(WCHAR));

   /* copy title */
   RtlpCopyParameterString(&Dest,
			   &Param->WindowTitle,
			   WindowTitle,
			   0);

   /* copy desktop */
   RtlpCopyParameterString(&Dest,
			   &Param->DesktopInfo,
			   DesktopInfo,
			   0);

   /* copy shell info */
   RtlpCopyParameterString(&Dest,
			   &Param->ShellInfo,
			   ShellInfo,
			   0);

   /* copy runtime info */
   RtlpCopyParameterString(&Dest,
			   &Param->RuntimeData,
			   RuntimeData,
			   0);

   RtlDeNormalizeProcessParams(Param);
   *ProcessParameters = Param;
   RtlReleasePebLock();

   return STATUS_SUCCESS;
}