Author: ion
Date: Sun Feb 19 10:06:31 2012
New Revision: 55706
URL:
http://svn.reactos.org/svn/reactos?rev=55706&view=rev
Log:
[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.
Modified:
trunk/reactos/dll/ntdll/def/ntdll.pspec
trunk/reactos/dll/ntdll/def/ntdll.spec
trunk/reactos/dll/win32/kernel32/client/dllmain.c
trunk/reactos/dll/win32/kernel32/client/proc.c
trunk/reactos/include/ndk/rtlfuncs.h
trunk/reactos/include/ndk/rtltypes.h
trunk/reactos/lib/rtl/timerqueue.c
trunk/reactos/lib/rtl/workitem.c
Modified: trunk/reactos/dll/ntdll/def/ntdll.pspec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/def/ntdll.pspec?…
==============================================================================
--- trunk/reactos/dll/ntdll/def/ntdll.pspec [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/def/ntdll.pspec [iso-8859-1] Sun Feb 19 10:06:31 2012
@@ -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)
Modified: trunk/reactos/dll/ntdll/def/ntdll.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/def/ntdll.spec?r…
==============================================================================
--- trunk/reactos/dll/ntdll/def/ntdll.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/def/ntdll.spec [iso-8859-1] Sun Feb 19 10:06:31 2012
@@ -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)
Modified: trunk/reactos/dll/win32/kernel32/client/dllmain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/dllmain.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/dllmain.c [iso-8859-1] Sun Feb 19 10:06:31
2012
@@ -220,6 +220,46 @@
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 @@
/* 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);
Modified: trunk/reactos/dll/win32/kernel32/client/proc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/proc.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/proc.c [iso-8859-1] Sun Feb 19 10:06:31 2012
@@ -544,7 +544,7 @@
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;
}
Modified: trunk/reactos/include/ndk/rtlfuncs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtlfuncs.h?rev…
==============================================================================
--- trunk/reactos/include/ndk/rtlfuncs.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/rtlfuncs.h [iso-8859-1] Sun Feb 19 10:06:31 2012
@@ -2410,6 +2410,14 @@
//
// Thread Pool Functions
//
+//
+NTSTATUS
+NTAPI
+RtlSetThreadPoolStartFunc(
+ IN PRTL_START_POOL_THREAD StartPoolThread,
+ IN PRTL_EXIT_POOL_THREAD ExitPoolThread
+);
+
NTSYSAPI
NTSTATUS
NTAPI
Modified: trunk/reactos/include/ndk/rtltypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtltypes.h?rev…
==============================================================================
--- trunk/reactos/include/ndk/rtltypes.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/rtltypes.h [iso-8859-1] Sun Feb 19 10:06:31 2012
@@ -520,6 +520,21 @@
(NTAPI *PRTL_BASE_PROCESS_START_ROUTINE)(
PTHREAD_START_ROUTINE StartAddress,
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
);
//
Modified: trunk/reactos/lib/rtl/timerqueue.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/timerqueue.c?rev=5…
==============================================================================
--- trunk/reactos/lib/rtl/timerqueue.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/timerqueue.c [iso-8859-1] Sun Feb 19 10:06:31 2012
@@ -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 @@
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 @@
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 @@
return status;
}
+ NtResumeThread(q->thread, NULL);
*NewTimerQueue = q;
return STATUS_SUCCESS;
}
Modified: trunk/reactos/lib/rtl/workitem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/workitem.c?rev=557…
==============================================================================
--- trunk/reactos/lib/rtl/workitem.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/workitem.c [iso-8859-1] Sun Feb 19 10:06:31 2012
@@ -14,6 +14,36 @@
#include <debug.h>
/* 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 @@
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 @@
InterlockedExchange((PLONG)Parameter,
1);
- RtlExitUserThread(Status);
+ RtlpExitThreadFunc(Status);
return 0;
}
@@ -647,7 +669,7 @@
}
NtClose(ThreadInfo.ThreadHandle);
- RtlExitUserThread(Status);
+ RtlpExitThreadFunc(Status);
return 0;
}
@@ -670,7 +692,7 @@
1);
/* Oops, too many worker threads... */
- RtlExitUserThread(Status);
+ RtlpExitThreadFunc(Status);
return 0;
}
@@ -743,7 +765,7 @@
}
}
- RtlExitUserThread(Status);
+ RtlpExitThreadFunc(Status);
return 0;
}
@@ -892,3 +914,16 @@
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;
+}