mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:12:57 +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;
|
PERESOURCE FsRtlPagingIoResources;
|
||||||
ULONG FsRtlPagingIoResourceSelector;
|
ULONG FsRtlPagingIoResourceSelector;
|
||||||
|
NTSTATUS NTAPI INIT_FUNCTION FsRtlInitializeWorkerThread();
|
||||||
|
|
||||||
static UCHAR LegalAnsiCharacterArray[] =
|
static UCHAR LegalAnsiCharacterArray[] =
|
||||||
{
|
{
|
||||||
|
@ -183,7 +184,7 @@ FsRtlInitSystem(VOID)
|
||||||
ExInitializeResource(&FsRtlPagingIoResources[i]);
|
ExInitializeResource(&FsRtlPagingIoResources[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return NT_SUCCESS(FsRtlInitializeWorkerThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS **********************************************************/
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/fsrtl/stackovf.c
|
* FILE: ntoskrnl/fsrtl/stackovf.c
|
||||||
* PURPOSE: Provides Stack Overflow support for File System Drivers
|
* PURPOSE: Provides Stack Overflow support for File System Drivers
|
||||||
* PROGRAMMERS: None.
|
* PROGRAMMERS: Pierre Schweitzer (pierre@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
@ -12,8 +12,65 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#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 *********************************************************/
|
/* 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
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
FsRtlpPostStackOverflow(IN PVOID Context,
|
FsRtlpPostStackOverflow(IN PVOID Context,
|
||||||
|
@ -21,14 +78,115 @@ FsRtlpPostStackOverflow(IN PVOID Context,
|
||||||
IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine,
|
IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine,
|
||||||
IN BOOLEAN IsPaging)
|
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 **********************************************************/
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
* @name FsRtlPostPagingFileStackOverflow
|
* @name FsRtlPostPagingFileStackOverflow
|
||||||
* @unimplemented NT 4.0
|
* @implemented NT 5.2
|
||||||
*
|
*
|
||||||
* The FsRtlPostPagingFileStackOverflow routine
|
* The FsRtlPostPagingFileStackOverflow routine
|
||||||
*
|
*
|
||||||
|
@ -54,7 +212,7 @@ FsRtlPostPagingFileStackOverflow(IN PVOID Context,
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
* @name FsRtlPostStackOverflow
|
* @name FsRtlPostStackOverflow
|
||||||
* @unimplemented NT 4.0
|
* @implemented NT 5.2
|
||||||
*
|
*
|
||||||
* The FsRtlPostStackOverflow routine
|
* The FsRtlPostStackOverflow routine
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue