コード例 #1
0
ファイル: thread.c プロジェクト: mutoso-mirrors/reactos
/*
 @implemented
*/
NTSTATUS
NTAPI
RtlCreateUserThread(IN HANDLE ProcessHandle,
                    IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
                    IN BOOLEAN CreateSuspended,
                    IN ULONG StackZeroBits OPTIONAL,
                    IN SIZE_T StackReserve OPTIONAL,
                    IN SIZE_T StackCommit OPTIONAL,
                    IN PTHREAD_START_ROUTINE StartAddress,
                    IN PVOID Parameter OPTIONAL,
                    OUT PHANDLE ThreadHandle OPTIONAL,
                    OUT PCLIENT_ID ClientId OPTIONAL)
{
    NTSTATUS Status;
    HANDLE Handle;
    CLIENT_ID ThreadCid;
    INITIAL_TEB InitialTeb;
    OBJECT_ATTRIBUTES ObjectAttributes;
    CONTEXT Context;

    /* First, we'll create the Stack */
    Status = RtlpCreateUserStack(ProcessHandle,
                                 StackReserve,
                                 StackCommit,
                                 StackZeroBits,
                                 &InitialTeb);
    if (!NT_SUCCESS(Status)) return Status;

    /* Next, we'll set up the Initial Context */
    RtlInitializeContext(ProcessHandle,
                         &Context,
                         Parameter,
                         StartAddress,
                         InitialTeb.StackBase);

    /* We are now ready to create the Kernel Thread Object */
    InitializeObjectAttributes(&ObjectAttributes,
                               NULL,
                               0,
                               NULL,
                               SecurityDescriptor);
    Status = ZwCreateThread(&Handle,
                            THREAD_ALL_ACCESS,
                            &ObjectAttributes,
                            ProcessHandle,
                            &ThreadCid,
                            &Context,
                            &InitialTeb,
                            CreateSuspended);
    if (!NT_SUCCESS(Status))
    {
        /* Free the stack */
        RtlpFreeUserStack(ProcessHandle, &InitialTeb);
    }
    else
    {
        /* Return thread data */
        if (ThreadHandle)
            *ThreadHandle = Handle;
        else
            NtClose(Handle);
        if (ClientId) *ClientId = ThreadCid;
    }

    /* Return success or the previous failure */
    return Status;
}
コード例 #2
0
ファイル: rtlexec.c プロジェクト: AlexiaChen/wrk_study
NTSTATUS
RtlCreateUserThread(
    IN HANDLE Process,
    IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
    IN BOOLEAN CreateSuspended,
    IN ULONG ZeroBits OPTIONAL,
    IN SIZE_T MaximumStackSize OPTIONAL,
    IN SIZE_T CommittedStackSize OPTIONAL,
    IN PUSER_THREAD_START_ROUTINE StartAddress,
    IN PVOID Parameter OPTIONAL,
    OUT PHANDLE Thread OPTIONAL,
    OUT PCLIENT_ID ClientId OPTIONAL
    )

/*++

Routine Description:

    This function creates a user mode thread in a user process.  The caller
    specifies the attributes of the new thread.  A handle to the thread, along
    with its Client Id are returned to the caller.

Arguments:

    Process - Handle to the target process in which to create the new thread.

    ThreadSecurityDescriptor - An optional pointer to the Security Descriptor
        give to the new thread.

    CreateSuspended - A boolean parameter that specifies whether or not the new
        thread is to be created suspended or not.  If TRUE, the new thread
        will be created with an initial suspend count of 1.  If FALSE then
        the new thread will be ready to run when this call returns.

    ZeroBits - This parameter is passed to the virtual memory manager
        when the stack is allocated.  Stacks are always allocated with the
        MEM_TOP_DOWN allocation attribute.

    MaximumStackSize - This is the maximum size of the stack.  This size
        will be rounded up to the next highest page boundary.  If zero is
        specified, then the default size will be 64K bytes.

    CommittedStackSize - This is the initial committed size of the stack.  This
        size is rounded up to the next highest page boundary and then an
        additional page is added for the guard page.  The resulting size
        will then be commited and the guard page protection initialized
        for the last committed page in the stack.

    StartAddress - The initial starting address of the thread.

    Parameter - An optional pointer to a 32-bit pointer parameter that is
        passed as a single argument to the procedure at the start address
        location.

    Thread - An optional pointer that, if specified, points to a variable that
        will receive the handle of the new thread.

    ClientId - An optional pointer that, if specified, points to a variable
        that will receive the Client Id of the new thread.

--*/

{
    NTSTATUS Status;
    CONTEXT ThreadContext={0};
    OBJECT_ATTRIBUTES ObjectAttributes;
    INITIAL_TEB InitialTeb;
    HANDLE ThreadHandle;
    CLIENT_ID ThreadClientId;

    //
    // Allocate a stack for this thread in the address space of the target
    // process.
    //

    Status = RtlpCreateStack( Process,
                              MaximumStackSize,
                              CommittedStackSize,
                              ZeroBits,
                              &InitialTeb
                            );
    if ( !NT_SUCCESS( Status ) ) {
        return( Status );
    }

    //
    // Create an initial context for the new thread.
    //


    try {
        RtlInitializeContext( Process,
                              &ThreadContext,
                              Parameter,
                              (PVOID)StartAddress,
                              InitialTeb.StackBase
                            );
    } except (EXCEPTION_EXECUTE_HANDLER) {
        RtlpFreeStack( Process, &InitialTeb );
        return GetExceptionCode ();
    }

    //
    // Now create a thread in the target process.  The new thread will
    // not have a name and its handle will not be inherited by other
    // processes.
    //

    InitializeObjectAttributes( &ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL,
                                ThreadSecurityDescriptor );
    Status = ZwCreateThread( &ThreadHandle,
                             THREAD_ALL_ACCESS,
                             &ObjectAttributes,
                             Process,
                             &ThreadClientId,
                             &ThreadContext,
                             &InitialTeb,
                             CreateSuspended
                           );
    if (!NT_SUCCESS( Status )) {
#if DBG
        DbgPrint( "NTRTL: RtlCreateUserThread Failed. NtCreateThread Status == %X\n",
                  Status );
#endif // DBG
        RtlpFreeStack( Process, &InitialTeb );
    } else {
        if (ARGUMENT_PRESENT( Thread )) {
            *Thread = ThreadHandle;
        } else {
            ZwClose (ThreadHandle);
        }

        if (ARGUMENT_PRESENT( ClientId )) {
            *ClientId = ThreadClientId;
        }

    }

    //
    // Return status
    //

    return( Status );
}