Author: pschweitzer
Date: Wed May 1 20:53:15 2013
New Revision: 58906
URL:
http://svn.reactos.org/svn/reactos?rev=58906&view=rev
Log:
[NTOSKRNL]
Implement post stack overflow functions (i.e. FsRtlPostStackOverflow() and
FsRtlPostPagingFileStackOverflow())
Modified:
trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c
trunk/reactos/ntoskrnl/fsrtl/stackovf.c
Modified: trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c [iso-8859-1] Wed May 1 20:53:15 2013
@@ -16,6 +16,7 @@
PERESOURCE FsRtlPagingIoResources;
ULONG FsRtlPagingIoResourceSelector;
+NTSTATUS NTAPI INIT_FUNCTION FsRtlInitializeWorkerThread();
static UCHAR LegalAnsiCharacterArray[] =
{
@@ -183,7 +184,7 @@
ExInitializeResource(&FsRtlPagingIoResources[i]);
}
- return TRUE;
+ return NT_SUCCESS(FsRtlInitializeWorkerThread());
}
/* PUBLIC FUNCTIONS **********************************************************/
Modified: trunk/reactos/ntoskrnl/fsrtl/stackovf.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/stackovf.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/stackovf.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/stackovf.c [iso-8859-1] Wed May 1 20:53:15 2013
@@ -3,7 +3,7 @@
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/fsrtl/stackovf.c
* PURPOSE: Provides Stack Overflow support for File System Drivers
- * PROGRAMMERS: None.
+ * PROGRAMMERS: Pierre Schweitzer (pierre(a)reactos.org)
*/
/* INCLUDES ******************************************************************/
@@ -12,8 +12,65 @@
#define NDEBUG
#include <debug.h>
+/* GLOBALS *******************************************************************/
+
+/* We have one queue for paging files, one queue for normal files
+ * Queue 0 is for non-paging files
+ * Queue 1 is for paging files
+ * Don't add new/change current queues unless you know what you do
+ * Most of the code relies on the fact that we have two queues in that order
+ */
+#define FSRTLP_MAX_QUEUES 2
+
+typedef struct _STACK_OVERFLOW_WORK_ITEM
+{
+
+ WORK_QUEUE_ITEM WorkItem;
+ PFSRTL_STACK_OVERFLOW_ROUTINE Routine;
+ PVOID Context;
+ PKEVENT Event;
+} STACK_OVERFLOW_WORK_ITEM, *PSTACK_OVERFLOW_WORK_ITEM;
+
+KEVENT StackOverflowFallbackSerialEvent;
+STACK_OVERFLOW_WORK_ITEM StackOverflowFallback;
+KQUEUE FsRtlWorkerQueues[FSRTLP_MAX_QUEUES];
+
/* PRIVATE FUNCTIONS *********************************************************/
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlStackOverflowRead(IN PVOID Context)
+{
+ PSTACK_OVERFLOW_WORK_ITEM WorkItem;
+
+ WorkItem = (PSTACK_OVERFLOW_WORK_ITEM)Context;
+
+ /* Put us as top IRP for current thread */
+ IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
+ /* And call FsRtlSORoutine */
+ WorkItem->Routine(WorkItem->Context, WorkItem->Event);
+
+ /* If we were using fallback workitem, don't free it, just reset event */
+ if (WorkItem == &StackOverflowFallback)
+ {
+ KeSetEvent(&StackOverflowFallbackSerialEvent, 0, FALSE);
+ }
+ /* Otherwise, free the work item */
+ else
+ {
+ ExFreePoolWithTag(WorkItem, 'Fsrs');
+ }
+
+ /* Reset top level */
+ IoSetTopLevelIrp(NULL);
+}
+
+/*
+ * @implemented
+ */
VOID
NTAPI
FsRtlpPostStackOverflow(IN PVOID Context,
@@ -21,14 +78,115 @@
IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine,
IN BOOLEAN IsPaging)
{
- UNIMPLEMENTED;
+ PSTACK_OVERFLOW_WORK_ITEM WorkItem;
+
+ /* Try to allocate a work item */
+ WorkItem = ExAllocatePoolWithTag(NonPagedPool, sizeof(STACK_OVERFLOW_WORK_ITEM),
'FSrs');
+ if (WorkItem == NULL)
+ {
+ /* If we failed, and we are not a paging file, just raise an error */
+ if (!IsPaging)
+ {
+ RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Otherwise, wait for fallback workitem to be available and use it */
+ KeWaitForSingleObject(&StackOverflowFallbackSerialEvent, Executive,
KernelMode, FALSE, NULL);
+ WorkItem = &StackOverflowFallback;
+ }
+
+ /* Initialize work item */
+ WorkItem->Context = Context;
+ WorkItem->Event = Event;
+ WorkItem->Routine = StackOverflowRoutine;
+ ExInitializeWorkItem(&WorkItem->WorkItem, FsRtlStackOverflowRead, WorkItem);
+
+ /* And queue it in the appropriate queue (paging or not?) */
+ KeInsertQueue(&FsRtlWorkerQueues[IsPaging], &WorkItem->WorkItem.List);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlWorkerThread(IN PVOID StartContext)
+{
+ KIRQL Irql;
+ PLIST_ENTRY Entry;
+ PWORK_QUEUE_ITEM WorkItem;
+ ULONG QueueId = (ULONG)StartContext;
+
+ /* Set our priority according to the queue we're dealing with */
+ KeSetPriorityThread(&PsGetCurrentThread()->Tcb, LOW_REALTIME_PRIORITY +
QueueId);
+
+ /* Loop for events */
+ for (;;)
+ {
+ /* Look for next event */
+ Entry = KeRemoveQueue(&FsRtlWorkerQueues[QueueId], KernelMode, NULL);
+ WorkItem = CONTAINING_RECORD(Entry, WORK_QUEUE_ITEM, List);
+
+ /* Call its routine (here: FsRtlStackOverflowRead) */
+ WorkItem->WorkerRoutine(WorkItem->Parameter);
+
+ /* Check we're still at passive level or bugcheck */
+ Irql = KeGetCurrentIrql();
+ if (Irql != PASSIVE_LEVEL)
+ {
+ KeBugCheckEx(IRQL_NOT_LESS_OR_EQUAL, (ULONG_PTR)WorkItem->WorkerRoutine,
+ (ULONG_PTR)Irql, (ULONG_PTR)WorkItem->WorkerRoutine,
+ (ULONG_PTR)WorkItem);
+ }
+ }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+INIT_FUNCTION
+FsRtlInitializeWorkerThread()
+{
+ ULONG i;
+ NTSTATUS Status;
+ HANDLE ThreadHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ /* Initialize each queue we have */
+ for (i = 0; i < FSRTLP_MAX_QUEUES; ++i)
+ {
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+
+ /* Initialize the queue and its associated thread and pass it the queue ID */
+ KeInitializeQueue(&FsRtlWorkerQueues[i], 0);
+ Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS,
&ObjectAttributes,
+ 0, 0, FsRtlWorkerThread, (PVOID)i);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Don't leak handle */
+ ZwClose(ThreadHandle);
+ }
+
+ /* Also initialize our fallback event, set it to ensure it's already usable */
+ KeInitializeEvent(&StackOverflowFallbackSerialEvent, SynchronizationEvent,
TRUE);
+
+ return Status;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*++
* @name FsRtlPostPagingFileStackOverflow
- * @unimplemented NT 4.0
+ * @implemented NT 5.2
*
* The FsRtlPostPagingFileStackOverflow routine
*
@@ -54,7 +212,7 @@
/*++
* @name FsRtlPostStackOverflow
- * @unimplemented NT 4.0
+ * @implemented NT 5.2
*
* The FsRtlPostStackOverflow routine
*