- Final ROSRTL removal patch. The next patch will remove the actual library and code.

- Changes:
    - CreateProcess
        * Cleanup creation of the initial thread using new utility functions and remove rosrtl
        * Almost entirely rewrote the function to support features such as:
            - SxS (locally only, patch will follow),
            - SFP (SAFER) (locally only, patch will follow),
            - DllPaths (locally only, patch will follow), 
            - Proper process environment/paramter block creation
            - Proper console handle management (needs more work in kernel32/csr),
            - Tokens/CreateProcessAsUser (locally only, patch will follow), 
            - Simpler code for path lookup, and more robust.
            - Support for "auto-correction" (see Raymond Chen's blog)
            - 16-bit/NE detection
            - A variety of creation flags are now properly supported
            - Added support for an undocumented-yet-known (see comment) shell flag
            - Alert for flags we don't support yet
            - Catch invalid flag combinations and other caller errors
            - Improve and correct path searcing to use documented behaviours
            - Created a multitude of helper functions to make the code easier to read
              and allow them to be used for other apis as time goes on.
    
    - BaseProcessStartup
        * Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
        * Correct prototype of Thread Startup function for this case.

This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.

svn path=/trunk/; revision=16730
This commit is contained in:
Alex Ionescu 2005-07-26 04:14:10 +00:00
parent 286cccb1de
commit 1e8c8e3fe6
4 changed files with 2083 additions and 2079 deletions

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@ _BaseThreadStartupThunk@0:
push ebx /* lpParameter */
push eax /* lpStartAddress */
push 0 /* Return EIP */
//jmp _BaseThreadStartup@8
jmp _BaseThreadStartup@8
_BaseProcessStartThunk@0:
@ -27,6 +27,6 @@ _BaseProcessStartThunk@0:
push eax /* lpStartAddress */
push 0 /* Return EIP */
//jmp _BaseProcessStartup@4
jmp _BaseProcessStartup@4
/* EOF */

View file

@ -1,13 +1,10 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/thread/thread.c
* PURPOSE: Thread functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* Tls functions are modified from WINE
* UPDATE HISTORY:
* Created 01/11/98
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Ariadne ( ariadne@xs4all.nl)
*
*/
@ -15,13 +12,9 @@
#include <k32.h>
/* FIXME */
#include <rosrtl/thread.h>
#define NDEBUG
#include "../include/debug.h"
/* FUNCTIONS *****************************************************************/
_SEH_FILTER(BaseThreadExceptionFilter)
{
@ -68,198 +61,195 @@ BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
ExitThread(uExitCode);
}
/*
* @implemented
*/
HANDLE STDCALL
CreateThread
(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
HANDLE
STDCALL
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
)
LPDWORD lpThreadId)
{
return CreateRemoteThread
(
NtCurrentProcess(),
/* Act as if we're going to create a remote thread in ourselves */
return CreateRemoteThread(NtCurrentProcess(),
lpThreadAttributes,
dwStackSize,
lpStartAddress,
lpParameter,
dwCreationFlags,
lpThreadId
);
lpThreadId);
}
/*
* @implemented
*/
HANDLE STDCALL
CreateRemoteThread
(
HANDLE hProcess,
HANDLE
STDCALL
CreateRemoteThread(HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
)
LPDWORD lpThreadId)
{
NTSTATUS Status;
INITIAL_TEB InitialTeb;
CONTEXT Context;
CLIENT_ID ClientId;
OBJECT_ATTRIBUTES LocalObjectAttributes;
POBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hThread;
CLIENT_ID cidClientId;
NTSTATUS nErrCode;
ULONG_PTR nStackReserve;
ULONG_PTR nStackCommit;
OBJECT_ATTRIBUTES oaThreadAttribs;
PIMAGE_NT_HEADERS pinhHeader =
RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
ULONG Dummy;
DPRINT
(
"hProcess %08X\n"
"lpThreadAttributes %08X\n"
"dwStackSize %08X\n"
"lpStartAddress %08X\n"
"lpParameter %08X\n"
"dwCreationFlags %08X\n"
"lpThreadId %08X\n",
hProcess,
lpThreadAttributes,
DPRINT("CreateRemoteThread: hProcess: %ld dwStackSize: %ld lpStartAddress"
": %p lpParameter: %lx, dwCreationFlags: %lx\n", hProcess,
dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
/* Clear the Context */
RtlZeroMemory(&Context, sizeof(CONTEXT));
/* Write PID */
ClientId.UniqueProcess = hProcess;
/* Create the Stack */
Status = BasepCreateStack(hProcess,
dwStackSize,
lpStartAddress,
lpParameter,
dwCreationFlags,
lpThreadId
);
/* FIXME: do more checks - e.g. the image may not have an optional header */
if(pinhHeader == NULL)
dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
dwStackSize : 0,
&InitialTeb);
if(!NT_SUCCESS(Status))
{
nStackReserve = 0x100000;
nStackCommit = PAGE_SIZE;
}
else
{
nStackReserve = pinhHeader->OptionalHeader.SizeOfStackReserve;
nStackCommit = pinhHeader->OptionalHeader.SizeOfStackCommit;
}
/* FIXME: this should be defined in winbase.h */
#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
#endif
/* use defaults */
if(dwStackSize == 0);
/* dwStackSize specifies the size to reserve */
else if(dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION)
nStackReserve = dwStackSize;
/* dwStackSize specifies the size to commit */
else
nStackCommit = dwStackSize;
/* fix the stack reserve size */
if(nStackCommit > nStackReserve)
nStackReserve = ROUNDUP(nStackCommit, 0x100000);
/* initialize the attributes for the thread object */
InitializeObjectAttributes
(
&oaThreadAttribs,
NULL,
0,
NULL,
NULL
);
if(lpThreadAttributes)
{
/* make the handle inheritable */
if(lpThreadAttributes->bInheritHandle)
oaThreadAttribs.Attributes |= OBJ_INHERIT;
/* user-defined security descriptor */
oaThreadAttribs.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor;
}
DPRINT
(
"RtlRosCreateUserThreadVa\n"
"(\n"
" ProcessHandle %p,\n"
" ObjectAttributes %p,\n"
" CreateSuspended %d,\n"
" StackZeroBits %d,\n"
" StackReserve %lu,\n"
" StackCommit %lu,\n"
" StartAddress %p,\n"
" ThreadHandle %p,\n"
" ClientId %p,\n"
" ParameterCount %u,\n"
" Parameters[0] %p,\n"
" Parameters[1] %p\n"
")\n",
hProcess,
&oaThreadAttribs,
dwCreationFlags & CREATE_SUSPENDED,
0,
nStackReserve,
nStackCommit,
BaseThreadStartup,
&hThread,
&cidClientId,
2,
lpStartAddress,
lpParameter
);
/* create the thread */
nErrCode = RtlRosCreateUserThreadVa
(
hProcess,
&oaThreadAttribs,
dwCreationFlags & CREATE_SUSPENDED,
0,
&nStackReserve,
&nStackCommit,
(PTHREAD_START_ROUTINE)BaseThreadStartup,
&hThread,
&cidClientId,
2,
lpStartAddress,
lpParameter
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
SetLastErrorByStatus(nErrCode);
SetLastErrorByStatus(Status);
return NULL;
}
DPRINT
(
"StackReserve %p\n"
"StackCommit %p\n"
"ThreadHandle %p\n"
"ClientId.UniqueThread %p\n",
nStackReserve,
nStackCommit,
hThread,
cidClientId.UniqueThread
);
/* Create Initial Context */
BasepInitializeContext(&Context,
lpParameter,
lpStartAddress,
InitialTeb.StackBase,
1);
/* success */
if(lpThreadId) *lpThreadId = (DWORD)cidClientId.UniqueThread;
/* initialize the attributes for the thread object */
ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes,
lpThreadAttributes,
NULL);
/* Create the Kernel Thread Object */
Status = NtCreateThread(&hThread,
THREAD_ALL_ACCESS,
ObjectAttributes,
hProcess,
&ClientId,
&Context,
&InitialTeb,
TRUE);
if(!NT_SUCCESS(Status))
{
BasepFreeStack(hProcess, &InitialTeb);
SetLastErrorByStatus(Status);
return NULL;
}
#ifdef SXS_SUPPORT_ENABLED
/* Are we in the same process? */
if (Process = NtCurrentProcess())
{
PTEB Teb;
PVOID ActivationContextStack;
PTHREAD_BASIC_INFORMATION ThreadBasicInfo;
PACTIVATION_CONTEXT_BASIC_INFORMATION ActivationCtxInfo;
ULONG_PTR Cookie;
/* Get the TEB */
Status = NtQueryInformationThread(hThread,
ThreadBasicIformation,
&ThreadBasicInfo,
sizeof(ThreadBasicInfo),
NULL);
/* Allocate the Activation Context Stack */
Status = RtlAllocateActivationContextStack(&ActivationContextStack);
Teb = ThreadBasicInfo.TebBaseAddress;
/* Save it */
Teb->ActivationContextStackPointer = ActivationContextStack;
/* Query the Context */
Status = RtlQueryInformationActivationContext(1,
0,
NULL,
ActivationContextBasicInformation,
&ActivationCtxInfo,
sizeof(ActivationCtxInfo),
NULL);
/* Does it need to be activated? */
if (!ActivationCtxInfo.hActCtx)
{
/* Activate it */
Status = RtlActivateActivationContextEx(1,
Teb,
ActivationCtxInfo.hActCtx,
&Cookie);
}
}
#endif
/* FIXME: Notify CSR */
/* Success */
if(lpThreadId) *lpThreadId = (DWORD)ClientId.UniqueThread;
/* Resume it if asked */
if (!(dwCreationFlags & CREATE_SUSPENDED))
{
NtResumeThread(hThread, &Dummy);
}
/* Return handle to thread */
return hThread;
}
/*
* @implemented
*/
VOID
STDCALL
ExitThread(DWORD uExitCode)
{
NTSTATUS Status;
BOOLEAN LastThread;
/*
* Terminate process if this is the last thread
* of the current process
*/
Status = NtQueryInformationThread(NtCurrentThread(),
ThreadAmILastThread,
&LastThread,
sizeof(BOOLEAN),
NULL);
if (NT_SUCCESS(Status) && LastThread)
{
/* Exit the Process */
ExitProcess(uExitCode);
}
/* Notify DLLs and TLS Callbacks of termination */
LdrShutdownThread();
/* Tell the Kernel to free the Stack */
NtCurrentTeb()->FreeStackOnTermination = TRUE;
NtTerminateThread(NULL, uExitCode);
/* We will never reach this place. This silences the compiler */
ExitThread(uExitCode);
}
/*
* @implemented
@ -330,37 +320,6 @@ GetCurrentThreadId(VOID)
return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
}
/*
* @implemented
*/
VOID STDCALL
ExitThread(DWORD uExitCode)
{
NTSTATUS Status;
BOOLEAN LastThread;
/*
* Terminate process if this is the last thread
* of the current process
*/
Status = NtQueryInformationThread(NtCurrentThread(),
ThreadAmILastThread,
&LastThread,
sizeof(BOOLEAN),
NULL);
if (NT_SUCCESS(Status) && LastThread == TRUE)
{
ExitProcess(uExitCode);
}
/* FIXME: notify csrss of thread termination */
LdrShutdownThread();
RtlRosExitUserThread(uExitCode);
}
/*
* @implemented
*/

View file

@ -312,22 +312,11 @@ MmCreateTeb(PEPROCESS Process,
/* Store stack information from InitialTeb */
if(InitialTeb != NULL)
{
/* fixed-size stack */
if(InitialTeb->PreviousStackBase && InitialTeb->PreviousStackLimit)
{
Teb->Tib.StackBase = InitialTeb->PreviousStackBase;
Teb->Tib.StackLimit = InitialTeb->PreviousStackLimit;
Teb->DeallocationStack = InitialTeb->PreviousStackLimit;
}
/* expandable stack */
else
{
Teb->Tib.StackBase = InitialTeb->StackBase;
Teb->Tib.StackLimit = InitialTeb->StackLimit;
Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
}
}
/* Return TEB Address */
DPRINT("Allocated: %x\n", Teb);