[RTL/NTDLL/KERNEL32]: Rtl provides worker queue and timer queue functionality, which queues a worker thread associated with a caller-supplied callback. In Windows, Rtl by default calls RtlCreateUserThread, but as soon as kernel32 loads, it's DllMain calls an exported function RtlSetThreadPoolStartFunc which changes that default to a special Base function that calls CreateRemoteThread instead. The net result is that Win32 processes using the Rtl functionality get their threads properly registered with CSRSS. In ReactOS, this did not happen, so when those threads called into CSRSS, CSRSS had no CSR_THREAD structure/state for them, which is why CsrCreateThread (and the API loop) are so badly hacked. This commit implements RtlSetThreadPoolStartFunc, implements the kernel32 base functions which wrap CreateRemoteThread, and implements the rtl functions which wrap RtlCreateUserThread. Services, Setup, and any ReactOS application using RPC now have the worker threads correctly registered.

svn path=/trunk/; revision=55706
This commit is contained in:
Alex Ionescu
2012-02-19 10:06:31 +00:00
parent 55e9cddf05
commit 07ea12ee5b
8 changed files with 124 additions and 21 deletions
+1 -1
View File
@@ -896,7 +896,7 @@
//@ stdcall RtlSetSecurityObjectEx
//@ stdcall RtlSetThreadErrorMode
@ stdcall RtlSetThreadIsCritical(long ptr long)
//@ stdcall RtlSetThreadPoolStartFunc
@ stdcall RtlSetThreadPoolStartFunc(ptr ptr)
@ stdcall RtlSetTimeZoneInformation(ptr)
//@ stdcall RtlSetTimer
@ stdcall RtlSetUnhandledExceptionFilter(ptr)
+1 -1
View File
@@ -896,7 +896,7 @@
;@ stdcall RtlSetSecurityObjectEx
;@ stdcall RtlSetThreadErrorMode
@ stdcall RtlSetThreadIsCritical(long ptr long)
;@ stdcall RtlSetThreadPoolStartFunc
@ stdcall RtlSetThreadPoolStartFunc(ptr ptr)
@ stdcall RtlSetTimeZoneInformation(ptr)
;@ stdcall RtlSetTimer
@ stdcall RtlSetUnhandledExceptionFilter(ptr)
@@ -220,6 +220,46 @@ BasepInitConsole(VOID)
return TRUE;
}
NTSTATUS
NTAPI
BaseCreateThreadPoolThread(IN PTHREAD_START_ROUTINE Function,
IN PVOID Parameter,
OUT PHANDLE ThreadHandle)
{
NTSTATUS Status;
/* Create a Win32 thread */
*ThreadHandle = CreateRemoteThread(NtCurrentProcess(),
NULL,
0,
Function,
Parameter,
CREATE_SUSPENDED,
NULL);
if (!(*ThreadHandle))
{
/* Get the status value if we couldn't get a handle */
Status = NtCurrentTeb()->LastStatusValue;
if (NT_SUCCESS(Status)) Status = STATUS_UNSUCCESSFUL;
}
else
{
/* Set success code */
Status = STATUS_SUCCESS;
}
/* All done */
return Status;
}
NTSTATUS
NTAPI
BaseExitThreadPoolThread(IN NTSTATUS ExitStatus)
{
/* Exit the thread */
ExitThread(ExitStatus);
}
BOOL
WINAPI
DllMain(HANDLE hDll,
@@ -246,6 +286,9 @@ DllMain(HANDLE hDll,
/* Set no filter intially */
GlobalTopLevelExceptionFilter = RtlEncodePointer(NULL);
/* Enable the Rtl thread pool and timer queue to use proper Win32 thread */
RtlSetThreadPoolStartFunc(BaseCreateThreadPoolThread, BaseExitThreadPoolThread);
/* Don't bother us for each thread */
LdrDisableThreadCalloutsForDll((PVOID)hDll);
+1 -1
View File
@@ -544,7 +544,7 @@ BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
sizeof(CSR_API_MESSAGE));
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
{
DPRINT1("Failed to tell csrss about new thread\n");
DPRINT1("Failed to tell csrss about new thread: %lx %lx\n", Status, CsrRequest.Status);
return CsrRequest.Status;
}
+8
View File
@@ -2410,6 +2410,14 @@ RtlGetCurrentProcessorNumber(
//
// Thread Pool Functions
//
//
NTSTATUS
NTAPI
RtlSetThreadPoolStartFunc(
IN PRTL_START_POOL_THREAD StartPoolThread,
IN PRTL_EXIT_POOL_THREAD ExitPoolThread
);
NTSYSAPI
NTSTATUS
NTAPI
+15
View File
@@ -522,6 +522,21 @@ typedef VOID
PVOID Parameter
);
//
// Worker Start/Exit Function
//
typedef NTSTATUS
(NTAPI *PRTL_START_POOL_THREAD)(
IN PTHREAD_START_ROUTINE Function,
IN PVOID Parameter,
OUT PHANDLE ThreadHandle
);
typedef NTSTATUS
(NTAPI *PRTL_EXIT_POOL_THREAD)(
IN NTSTATUS ExitStatus
);
//
// Declare empty structure definitions so that they may be referenced by
// routines before they are defined
+5 -3
View File
@@ -19,6 +19,8 @@
/* FUNCTIONS ***************************************************************/
extern PRTL_START_POOL_THREAD RtlpStartThreadFunc;
extern PRTL_EXIT_POOL_THREAD RtlpExitThreadFunc;
HANDLE TimerThreadHandle = NULL;
NTSTATUS
@@ -239,7 +241,7 @@ static void WINAPI timer_queue_thread_proc(LPVOID p)
NtClose(q->event);
RtlDeleteCriticalSection(&q->cs);
RtlFreeHeap(RtlGetProcessHeap(), 0, q);
RtlExitUserThread(STATUS_SUCCESS);
RtlpExitThreadFunc(STATUS_SUCCESS);
}
static void queue_destroy_timer(struct queue_timer *t)
@@ -285,8 +287,7 @@ NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue)
RtlFreeHeap(RtlGetProcessHeap(), 0, q);
return status;
}
status = RtlCreateUserThread(NtCurrentProcess(), NULL, FALSE, 0, 0, 0,
(PTHREAD_START_ROUTINE)timer_queue_thread_proc, q, &q->thread, NULL);
status = RtlpStartThreadFunc((PVOID)timer_queue_thread_proc, q, &q->thread);
if (status != STATUS_SUCCESS)
{
NtClose(q->event);
@@ -294,6 +295,7 @@ NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue)
return status;
}
NtResumeThread(q->thread, NULL);
*NewTimerQueue = q;
return STATUS_SUCCESS;
}
+50 -15
View File
@@ -15,6 +15,36 @@
/* FUNCTIONS ***************************************************************/
NTSTATUS
NTAPI
RtlpStartThread(IN PTHREAD_START_ROUTINE Function,
IN PVOID Parameter,
OUT PHANDLE ThreadHandle)
{
/* Create a native worker thread -- used for SMSS, CSRSS, etc... */
return RtlCreateUserThread(NtCurrentProcess(),
NULL,
TRUE,
0,
0,
0,
Function,
Parameter,
ThreadHandle,
NULL);
}
NTSTATUS
NTAPI
RtlpExitThread(IN NTSTATUS ExitStatus)
{
/* Kill a native worker thread -- used for SMSS, CSRSS, etc... */
return NtTerminateThread(NtCurrentThread(), ExitStatus);
}
PRTL_START_POOL_THREAD RtlpStartThreadFunc = RtlpStartThread;
PRTL_EXIT_POOL_THREAD RtlpExitThreadFunc = RtlpExitThread;
#define MAX_WORKERTHREADS 0x100
#define WORKERTHREAD_CREATION_THRESHOLD 0x5
@@ -141,19 +171,11 @@ RtlpStartWorkerThread(PTHREAD_START_ROUTINE StartRoutine)
Timeout.QuadPart = -10000LL; /* Wait for 100ms */
/* Start the thread */
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
FALSE,
0,
0,
0,
StartRoutine,
(PVOID)&WorkerInitialized,
&ThreadHandle,
NULL);
Status = RtlpStartThreadFunc(StartRoutine, (PVOID)&WorkerInitialized, &ThreadHandle);
if (NT_SUCCESS(Status))
{
NtResumeThread(ThreadHandle, NULL);
/* Poll until the thread got a chance to initialize */
while (WorkerInitialized == 0)
{
@@ -568,7 +590,7 @@ InitFailed:
InterlockedExchange((PLONG)Parameter,
1);
RtlExitUserThread(Status);
RtlpExitThreadFunc(Status);
return 0;
}
@@ -647,7 +669,7 @@ Wait:
}
NtClose(ThreadInfo.ThreadHandle);
RtlExitUserThread(Status);
RtlpExitThreadFunc(Status);
return 0;
}
@@ -670,7 +692,7 @@ RtlpWorkerThreadProc(IN PVOID Parameter)
1);
/* Oops, too many worker threads... */
RtlExitUserThread(Status);
RtlpExitThreadFunc(Status);
return 0;
}
@@ -743,7 +765,7 @@ RtlpWorkerThreadProc(IN PVOID Parameter)
}
}
RtlExitUserThread(Status);
RtlpExitThreadFunc(Status);
return 0;
}
@@ -892,3 +914,16 @@ RtlSetIoCompletionCallback(IN HANDLE FileHandle,
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
RtlSetThreadPoolStartFunc(IN PRTL_START_POOL_THREAD StartPoolThread,
IN PRTL_EXIT_POOL_THREAD ExitPoolThread)
{
RtlpStartThreadFunc = StartPoolThread;
RtlpExitThreadFunc = ExitPoolThread;
return STATUS_SUCCESS;
}