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?re... ============================================================================== --- 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?r... ============================================================================== --- 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@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 *