mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[NTOSKRNL]
Implement post stack overflow functions (i.e. FsRtlPostStackOverflow() and FsRtlPostPagingFileStackOverflow()) svn path=/trunk/; revision=58906
This commit is contained in:
parent
279b9507fd
commit
44099efad5
2 changed files with 164 additions and 5 deletions
|
@ -16,6 +16,7 @@
|
|||
|
||||
PERESOURCE FsRtlPagingIoResources;
|
||||
ULONG FsRtlPagingIoResourceSelector;
|
||||
NTSTATUS NTAPI INIT_FUNCTION FsRtlInitializeWorkerThread();
|
||||
|
||||
static UCHAR LegalAnsiCharacterArray[] =
|
||||
{
|
||||
|
@ -183,7 +184,7 @@ FsRtlInitSystem(VOID)
|
|||
ExInitializeResource(&FsRtlPagingIoResources[i]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return NT_SUCCESS(FsRtlInitializeWorkerThread());
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
|
|
@ -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 @@ FsRtlpPostStackOverflow(IN PVOID Context,
|
|||
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 @@ FsRtlPostPagingFileStackOverflow(IN PVOID Context,
|
|||
|
||||
/*++
|
||||
* @name FsRtlPostStackOverflow
|
||||
* @unimplemented NT 4.0
|
||||
* @implemented NT 5.2
|
||||
*
|
||||
* The FsRtlPostStackOverflow routine
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue